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