60 votes

Y a-t-il une différence entre les symboles '&&' et ';' dans un terminal BASH standard ?

Il semble que les deux signalent à BASH de commencer avec une autre commande suivant les symboles, mais y a-t-il une différence distincte ?

82voto

Avec cette ligne:

command1 && command2

la commande2 sera exécutée si (et seulement si) la commande1 renvoie un statut de sortie zéro, tandis que dans cette ligne:

command1 ; command2

les deux commandes command1 et command2 seront exécutées quoi qu'il arrive. Le point-virgule vous permet de taper plusieurs commandes sur une seule ligne.

43voto

Alex319 Points 191

Vous pouvez essayer la différence vous-même :

  1. ls /chemin/invalide && echo "bonjour!"
    puisque /invalid/path n'existe pas, ls ne peut pas vous montrer la liste des répertoires. Il échouera avec un message d'erreur : "ls: /invalid/path: Aucun fichier ou dossier de ce type".
    La deuxième moitié de la commande (echo "bonjour!") n'est même pas exécutée car la première moitié a échoué.

  2. ls /chemin/invalide ; echo "bonjour!"
    Le même message d'erreur apparaît comme précédemment, mais cette fois, la deuxième partie est exécutée !
    ls: /invalid/path: Aucun fichier ou dossier de ce type
    bonjour!

Pourquoi est-ce utile ?
Supposez que vous vouliez extraire un fichier appelé archive.tar.gz
Vous pourriez utiliser la commande tar zxvf archive.tar.gz && rm archive.tar.gz.
Si pour une raison quelconque l'extraction de l'archive échoue, la deuxième partie n'est pas exécutée ! Vous pouvez réessayer.

Si vous utilisez ; dans la même situation, l'archive est supprimée et vous ne pouvez pas réessayer.

8voto

Peter Hilton Points 10580

Mise à jour : J'ai ajouté un script pour mettre en évidence certaines des pièges possibles :

Comme personne d'autre n'a mentionné "||", je vais le faire

Mise à jour 2 : quelques modifications importantes ici
&& est comme un "puis" d'une instruction "si" qui répond à "vrai"

|| n'est PAS comme le "sinon" d'une instruction "si"...
|| est comme un "puis" d'une instruction "si" qui répond à "faux"

Plus spécifiquement, && teste la valeur de retour $? de l'instruction précédente la plus récemment exécutée et passe le contrôle à l'instruction ou au sous-shell immédiatement suivant le &&... il ne passe le contrôle que si $? est vrai.

|| est similaire, et est souvent vu après une instruction &&, mais il teste une valeur de retour fausse ($?) de l'instruction précédente la plus récemment exécutée... NTC!, Nota Bene! Notez bien!.... si l'instruction précédente est une instruction && qui renvoie false quand vous vous attendez à ce qu'elle soit vraie, alors || répondra au false, donc mélanger les deux sur la même ligne peut être risqué

Le point principal que j'essaie de faire est en relation avec une erreur que j'ai commise. c.-à-d.
## [[condition]] && A || B
n'est pas ne se comporte pas comme un ternaire de style C/C++. c.-à-d.
// (condition) ? A : B
Voir le script ci-dessous pour des exemples de résultats "inattendus" de "A"

Le test de base et l'instruction && et || doit être sur la même ligne...


Exécutez ce script pour voir où les choses peuvent mal tourner lors de l'utilisation de && et ||
L'instruction la plus récemment exécutée peut ne pas être celle que vous attendez..

[[ condition]] && echo Bonjour || echo Au revoir .... est généralement sûr,
car un echo bien formé renverra vrai.
mais que se passe-t-il si vous accédez à un fichier qui n'existe pas ?

#!/bin/bash
#
# "codes de retour attendus" signifie: censé se comporter comme un test de condition normale AND / OR
#
if [[ "$1" != "" ]] ; then exit $1; fi # appel récursif pour renvoyer une valeur $? arbitraire (décimale)
echo
echo 'test 1: Tous les codes de retour sont "comme prévu"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. la condition est vraie" || echo  " ((1==1)) rc=$? ..||.. la condition est fausse"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. la condition est vraie" || echo "  \$0  0   rc=$? ..||.. la condition est fausse"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. la condition est vraie" || echo  " ((1!=1)) rc=$? ..||.. la condition est fausse"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. la condition est vraie" || echo "  \$0  1   rc=$? ..||.. la condition est fausse"
echo
echo 'test 2: Maintenant introduisez quelques erreurs "inattendues" dans le premier des &&/|| couples' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. la condition est vraie"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. la condition est fausse"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. la condition est vraie"; $0 2)  || echo "  \$0  0   rc=$? ..||.. la condition est fausse"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. la condition est vraie"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. la condition est fausse"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. la condition est vraie"; $0 4)  || echo "  \$0  1   rc=$? ..||.. la condition est fausse"
echo
echo 'test 3: Changez maintenant l'ordre des instructions && et ||, en utilisant des codes de retour "comme prévu"'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. la condition est vraie" && echo  " ((1==1)) rc=$? ..&&.. la condition est fausse"
  $0  0   || echo "  \$0  0   rc=$? ..||.. la condition est vraie" && echo "  \$0  0   rc=$? ..&&.. la condition est fausse"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. la condition est vraie" && echo  " ((1!=1)) rc=$? ..&&.. la condition est fausse"
  $0  1   || echo "  \$0  1   rc=$? ..||.. la condition est vraie" && echo "  \$0  1   rc=$? ..&&.. la condition est fausse"
echo
echo 'test 4: Avec l'ordre des instructions && et || toujours inversé, introduisez des erreurs "inattendues" dans le premier des &&/|| couple' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. la condition est vraie"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. la condition est fausse"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. la condition est vraie"; $0 2)  || echo "  \$0  0   rc=$? ..||.. la condition est fausse"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. la condition est vraie"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. la condition est fausse"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. la condition est vraie"; $0 4)  || echo "  \$0  1   rc=$? ..||.. la condition est fausse"

exit 

8voto

Matthew Ruston Points 2319

&& est ET, ce qui signifie que la deuxième commande ne s'exécutera que si la première a renvoyé vrai (pas d'erreurs).

1voto

user10487 Points 11

Essayer

faux && echo "bonjour"

et

faux ; echo "bonjour"

voir la différence

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X