Palavras-chave como if
, then
, else
, fi
, for
, case
e assim por diante necessidade de estar em um lugar onde a Shell espera um nome de comando. Caso contrário, eles são tratados como palavras comuns. Por exemplo,
echo if
apenas imprime if
, não inicia uma instrução condicional.
Assim, na linha
if [ -r "$NAME" -af "$NAME" ] then
a palavra then
é um argumento do comando [
(do qual reclamaria se alguma vez fosse executado). O shell continua procurando o then
e encontra uma fi
posição de comando. Como há um if
que ainda está procurando then
, o fi
é inesperado, há um erro de sintaxe.
Você precisa colocar um terminador de comando antes then
para que seja reconhecido como uma palavra-chave. O terminador de comando mais comum é uma quebra de linha, mas antes then
, é comum usar um ponto-e-vírgula (que tem exatamente o mesmo significado que uma quebra de linha).
if [ -r "$NAME" -af "$NAME" ]; then
ou
if [ -r "$NAME" -af "$NAME" ]
then
Depois de corrigir isso, você receberá outro erro do comando [
porque ele não entende -af
. Você provavelmente quis dizer
if [ -r "$NAME" -a -f "$NAME" ]; then
Embora os comandos de teste pareçam opções, você não pode agrupá-los dessa maneira. Eles são operadores do [
comando e precisam ser cada um uma palavra separada (como faça [
e ]
).
A propósito, embora [ -r "$NAME" -a -f "$NAME" ]
funcione, eu recomendo escrever
[ -r "$NAME" ] && [ -f "$NAME" ]
ou
[[ -r $NAME && -f $NAME ]]
É melhor manter [ … ]
condicionais simples, porque o [
comando não pode distinguir operadores de operando facilmente. Se $NAME
parecer com um operador e aparecer em uma posição em que o operador é válido, ele poderá ser analisado como operador. Isso não acontecerá nos casos simples vistos nesta resposta, mas casos mais complexos podem ser arriscados. Escrever isso com chamadas separadas [
e usar os operadores lógicos do shell evita esse problema.
A segunda sintaxe usa a [[ … ]]
construção condicional existente no bash (e ksh e zsh, mas não sh simples). Esta construção é sintaxe especial, enquanto [
é analisado como qualquer outro comando, assim você pode usar coisas como &&
dentro e você não precisa variáveis cotação exceto em argumentos para alguns operadores de cordas ( =
, ==
, !=
, =~
) (ver Quando é colocar aspas necessário ? para detalhes).