web-dev-qa-db-fra.com

Quelle est la différence entre "&&" et ";" lors du chaînage des commandes

Quelle est la différence entre les méthodes de chaînage de commandes suivantes?

cmd1; cmd2
cmd1 && cmd2
116
varesa

Supposons qu'il y ait command1 && command2.

Dans ce cas command2 sera exécuté si et seulement si command1 n'a renvoyé aucun état de sortie.

; n'est qu'un séparateur de commandes. Donc command2 sera exécuté quel que soit command1 revenu.

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

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

cmd1; cmd2 exécute cmd1, puis cmd2, peu importe ce que. C'est exactement équivalent à mettre cmd1 et cmd2 sur des lignes séparées¹. Le statut de retour de cette commande composée est celui de cmd2.

cmd1 && cmd2 exécute cmd1. Ensuite, si l'état de sortie de cmd1 est zéro, cmd2 est exécuté. Le statut de retour de cette commande composée est celui de cmd1 s'il est différent de zéro (donc cmd2 n'a pas fonctionné), et celle de cmd2 sinon (s'il a fonctionné).

if cmd1; then cmd2; fi est principalement équivalent à cmd1 && cmd2. La principale différence est que la version avec if renvoie 0 si cmd1 renvoie un statut différent de zéro.

Une commande renvoie 0 pour indiquer la réussite et un code d'erreur différent de zéro (entre 1 et 255, généralement entre 1 et 125 car les valeurs supérieures ont d'autres significations) pour indiquer l'échec. Donc cmd1; cmd2 signifie "exécuter ces commandes dans l'ordre, peu importe", tandis que cmd1 && cmd2 signifie "exécuter ces commandes, mais arrêtez immédiatement si la première commande échoue".

Vous pouvez demander au shell de passer en mode "sortie en cas d'erreur" en exécutant set -e. Dans ce mode, le shell se ferme dès qu'une commande renvoie un état différent de zéro, sauf dans les constructions conditionnelles (le côté gauche de && ou ||, la partie condition de if et while). Ainsi, sous set -e, ; (ou une nouvelle ligne) équivaut effectivement à &&².

¹ En termes de flux de contrôle, c'est. Les retours à la ligne et les points-virgules sont exécutés exactement de la même manière, mais ils ne sont pas analysés exactement de la même manière, par ex. alias ls=true; ls exécute ls et non true car l'analyseur effectue une résolution d'alias sur ls avant d'exécuter la définition d'alias.
¹ Cela ne veut pas dire que vous pouvez remplacer aveuglément && par ; si vous avez ajouté set -e. Par exemple, ; a une priorité inférieure à &&, donc cmd1 && cmd2 || cmd3 est équivalent à set -e; { cmd1; cmd2; } || cmd3. Aussi, set -e interagit mal avec les sous-coquilles - les détails dérailleraient trop cette réponse.

La première ligne exécutera une commande après l'autre, que la première ait réussi ou non. La deuxième ligne est un exemple de logique Shell: elle n'exécutera la deuxième commande que si la première a réussi. Ceci est dû au fait && est logique and. Par conséquent, si la première commande échoue, l'état logique de la ligne entière est connu pour être faux et il n'est pas nécessaire d'évaluer la deuxième commande.

21
Wojtek

Plus pratique, il y a une différence entre

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

et

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

. En plus, c'est une façon stupide, le premier supprimera tout votre système de fichiers (ou $ HOME, selon la façon dont il est appelé) car il exécute rm indépendamment du fait que cd ait réussi ou non.

3
Reactormonk