Quando um comando não é encontrado, o status de saída é 127. Você poderia usá-lo para determinar que o comando não foi encontrado:
until
printf "Enter a command: "
read command
"$command"
[ "$?" -ne 127 ]
do
echo Try again
done
Embora os comandos geralmente não retornem um status de saída 127 (no caso em que entraria em conflito com o valor especial padrão usado pelos shells), há alguns casos em que um comando pode retornar genuinamente um status de saída 127: um script cujo último comando não pode ser encontrado.
bash
e zsh
tem uma função especial command_not_found_handler
(há um erro de digitação em bash
como é chamado command_not_found_handle
), que quando definido é executado quando um comando não é encontrado. Mas ele é executado em um contexto de subshell e também pode ser executado em comandos não encontrados durante a execução de uma função.
Você pode ficar tentado a verificar previamente a existência do comando usando type
ou command -v
, mas cuidado:
"$commands"
é analisado como um simples comando e os aliases não são expandidos, enquanto type
ou command
retornaria true também para aliases e palavras-chave shell.
Por exemplo, com command=for
, type -- "$command"
retornaria true, mas "$command"
retornaria (muito provavelmente) um erro comando não encontrado .
which
pode falhar por vários outros motivos.
O ideal é que você queira algo que retorne verdadeiro se o comando existir como uma função, um shell interno ou um comando externo.
hash
atenderia a esses critérios pelo menos para ash
e bash
(não yash
nem ksh
nem zsh
). Então, isso funcionaria em bash
ou ash
:
while
printf "Enter a command: "
read command
do
if hash -- "$command" 2> /dev/null; then
"$command"
break
fi
echo Try again
done
Um problema com isso é que hash
retorna true também para um diretório (para um caminho para um diretório incluindo /
). Enquanto se você tentar executá-lo, enquanto ele não retornar um erro comando não encontrado , ele retornará um erro Is a directory
ou Permission Denied
. Se você quiser cobrir isso, você poderia fazer:
while
printf "Enter a command: "
read command
do
if hash -- "$command" 2> /dev/null &&
{ [ "${command#*/}" != "$command" ] || [ ! -d "$command" ];}
then
"$command"
break
fi
echo Try again
done