Qual é a diferença entre “&&” e “;” ao encadear comandos [duplicados]

104

Qual é a diferença entre os seguintes métodos de comando de encadeamento?

cmd1; cmd2
cmd1 && cmd2
    
por varesa 22.04.2012 / 20:01

4 respostas

143

Suponha que haja command1 && command2 .

Nesse caso, command2 será executado se e somente se command1 retornar zero status de saída.

; é apenas um separador de comando. Assim, command2 será executado, seja qual for o command1 retornado.

$> [[ "a" = "b" ]] && echo ok 

$> [[ "a" = "b" ]]; echo ok 
ok
    
por 22.04.2012 / 20:03
31

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.

    
por 23.04.2012 / 01:45
21

A primeira linha executará um comando após o outro, independentemente de o primeiro ter sido bem-sucedido ou não. A segunda linha é um exemplo de lógica de shell: ele só executará o segundo comando se o primeiro for bem-sucedido. Isso ocorre porque && é lógico and . Portanto, se o primeiro comando falhar, o estado lógico da linha inteira é conhecido como falso e não há necessidade de avaliar o segundo comando.

    
por 22.04.2012 / 20:03
3

Mais prático, há uma diferença entre

cd /backup/old; rm -rf -- *

e

cd /backup/old && rm -rf -- *

Além de ser uma maneira estúpida, o primeiro removerá todo o seu sistema de arquivos (ou $ HOME, dependendo de como ele é chamado), porque ele executa rm , independentemente de o cd ser bem-sucedido ou não.

    
por 23.04.2012 / 17:43

Tags