Palavras-chave como if
, then
, else
, fi
, for
, case
e assim por diante precisam estar em um local onde o shell espera um nome de comando. Caso contrário, eles são tratados como palavras comuns. Por exemplo,
echo if
imprime apenas if
, ele 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 se queixaria se alguma vez fosse executado). O shell continua procurando pelo then
e localiza um fi
na posição de comando. Como há um if
que ainda está procurando por seu then
, o fi
é inesperado, há um erro de sintaxe.
Você precisa colocar um terminador de comando antes de then
para que seja reconhecido como uma palavra-chave. O terminador de comando mais comum é uma quebra de linha, mas antes de 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 não entende -af
. Você supostamente 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 [
e ]
).
A propósito, embora [ -r "$NAME" -a -f "$NAME" ]
funcione, recomendo escrever
[ -r "$NAME" ] && [ -f "$NAME" ]
ou
[[ -r $NAME && -f $NAME ]]
É melhor manter [ … ]
condicionais simples porque o comando [
não consegue distinguir facilmente operadores de operando. Se $NAME
se parece com um operador e aparece em uma posição onde o operador é válido, ele pode ser analisado como um operador. Isso não acontecerá nos casos simples vistos nesta resposta, mas casos mais complexos podem ser arriscados. Escrever isso com chamadas separadas para [
e usar os operadores lógicos do shell evita esse problema.
A segunda sintaxe usa a construção condicional [[ … ]]
que existe no bash (e ksh e zsh, mas não sh simples). Essa construção é sintaxe especial, enquanto [
é analisada como qualquer outro comando, portanto, é possível usar coisas como &&
dentro e você não precisa citar variáveis, exceto em argumentos para alguns operadores de string ( =
, ==
, !=
, =~
) (consulte Quando é necessário fazer uma dupla citação? para detalhes).