cmd1; cmd2
executa cmd1
e, em seguida, cmd2
, não importa o quê. É exatamente equivalente a colocar cmd1
e cmd2
em linhas separadas¹. O status de retorno desse comando composto é de cmd2
.
cmd1 && cmd2
executa cmd1
. Em seguida, se o status de saída de cmd1
for zero, cmd2
será executado. O status de retorno desse comando composto é cmd1
se for diferente de zero (portanto, cmd2
não foi executado) e cmd2
(caso tenha sido executado).
if cmd1; then cmd2; fi
é principalmente equivalente a cmd1 && cmd2
. A principal diferença é que a versão com if
retorna 0 se cmd1
retornar um status diferente de zero.
Um comando retorna 0 para indicar sucesso, e um código de erro diferente de zero (entre 1 e 255, geralmente entre 1 e 125, como valores mais altos têm outros significados) para indicar falha. Assim, cmd1; cmd2
significa “execute estes comandos em seqüência, não importa o que”, enquanto cmd1 && cmd2
significa “execute estes comandos, mas pare imediatamente se o primeiro comando falhar”.
Você pode dizer ao shell para entrar no modo "sair no erro" executando set -e
. Nesse modo, o shell sai assim que qualquer comando retorna um status diferente de zero, exceto em construções condicionais (o lado esquerdo de &&
ou ||
, a parte de condição de if
e while
). Assim, sob set -e
, ;
(ou uma nova linha) é efetivamente equivalente a &&
².
¹ Em termos de fluxo de controle, isto é. As novas linhas e os pontos-e-vírgulas são executados exatamente da mesma maneira, mas não são analisados exatamente da mesma maneira. alias ls=true; ls
executa ls
e não true
porque o analisador executa resolução de alias em ls
antes de executar a definição de alias.
Sub Isso não quer dizer que você pode substituir cegamente &&
por ;
se você adicionou set -e
. Por exemplo, ;
tem precedência menor que &&
, então cmd1 && cmd2 || cmd3
é equivalente a set -e; { cmd1; cmd2; } || cmd3
. Além disso, set -e
interage mal com subcamadas - os detalhes podem atrapalhar essa resposta muito longe.