A maneira como você está usando &&
e ||
é uma lista, não uma condicional.
Lists
A list is a sequence of one or more pipelines separated by one of the
operators ;, &, &&, or ⎪⎪, and optionally terminated by one of ;, &, or
<newline>.
Of these list operators, && and ⎪⎪ have equal precedence, followed by ;
and &, which have equal precedence.
A sequence of one or more newlines may appear in a list instead of a
semicolon to delimit commands.
If a command is terminated by the control operator &, the shell executes
the command in the background in a subshell. The shell does not wait for
the command to finish, and the return status is 0. Commands
separated by a ; are executed sequentially; the shell waits for each
command to terminate in turn. The return status is the exit status of
the last command executed.
AND and OR lists are sequences of one of more pipelines separated by the
&& and ⎪⎪ control operators, respectively. AND and OR lists are executed
with left associativity. An AND list has the form
command1 && command2
command2 is executed if, and only if, command1 returns an exit status of
zero.
An OR list has the form
command1 ⎪⎪ command2
command2 is executed if and only if command1 returns a non-zero exit
status. The return status of AND and OR lists is the exit status of the
last command executed in the list.
Se você der uma olhada neste SO Q & A intitulado: Operadores lógicos simples no BASH , @Gilles answer é tão conciso quanto possível em termos de explicar como lidar com if / then blocks no Bash.
Corrida re-fatorada # 1
Portanto, uma versão reformulada da sua declaração if/then
:
[[ -e cli.tar.gz && 'tar -xvf cli.tar.gz -C ~/' ||
echo "cli.tar.gz can not be found. Exiting" >&2 && exit 1
ficaria assim:
if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1; fi
Ou expandido para legibilidade:
if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then
echo "cli.tar.gz can not be found. Exiting" >&2
exit 1
fi
Exemplo de execução
Dados da amostra. Conteúdo do tarball:
$ tar ztvf cli.tar.gz
drwxrwxr-x saml/saml 0 2013-11-13 08:26 1/
drwxrwxr-x saml/saml 0 2013-11-13 08:26 1/2/
drwxrwxr-x saml/saml 0 2013-11-13 08:26 1/2/3/
drwxrwxr-x saml/saml 0 2013-11-13 08:26 1/2/3/4/
Informações do arquivo:
$ ls -l cli.tar.gz
-rw-rw-r-- 1 saml saml 146 Nov 13 08:27 cli.tar.gz
$ ls out/
1
Executando nosso comando:
$ if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1; fi
Nada aconteceu. Se nós removermos o diretório de saída. out
:
$ mv out out_ORIG
E execute novamente:
$ if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; fi
tar: out: Cannot chdir: No such file or directory
tar: Error is not recoverable: exiting now
cli.tar.gz can not be found. Exiting
O que aconteceu? Por um lado você geralmente não quer misturar a execução de comandos em um if / then como você está tentando fazer. Há muitos problemas que podem dar errado.
Corrida re-fatorada # 2
Em vez disso, eu estruturaria meu código dessa forma, já que isso nos dá o caminho mais fácil para lidar com os problemas à medida que eles surgem, em vez de tentar construir algum código ridículo que até você, o autor, terá dificuldades em entender. você estava fazendo!
if [[ -e cli.tar.gz ]]; then
cmdOutput=$(tar xvf cli.tar.gz -C out 2>&1);
if [[ $? != 0 ]]; then
echo "cli.tar.gz can not be found. Exiting" >&2
exit 1
fi
fi
Exemplo
$ ls -l |grep -E "cli|out"
-rw-rw-r-- 1 saml saml 146 Nov 13 08:27 cli.tar.gz
drwxrwxr-x 3 saml saml 4096 Nov 13 09:28 out
Agora execute nosso comando (nada acontece):
$ if [[ -e cli.tar.gz ]]; then cmdOutput=$(tar xvf cli.tar.gz -C out 2>&1); if [[ $? != 0 ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1;fi;fi
$
Agora execute nosso comando (sem dir. out present):
$ rm -fr out
$ ls -l |grep -E "cli|out"
-rw-rw-r-- 1 saml saml 146 Nov 13 08:27 cli.tar.gz
$ if [[ -e cli.tar.gz ]]; then cmdOutput=$(tar xvf cli.tar.gz -C out 2>&1); if [[ $? != 0 ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1;fi;fi
cli.tar.gz can not be found. Exiting