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

57

Ils semblent tous les deux indiquer à BASH de commencer par une autre commande suivant les symboles, mais existe-t-il une différence nette?

Michael Terry
la source

Réponses:

76

Avec cette ligne:

command1 && command2

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

command1 ; command2

commande1 et commande2 seront exécutés indépendamment. Le point-virgule vous permet de saisir plusieurs commandes sur une seule ligne.


la source
1
Intéressant! Je pensais que ce serait peut-être plus confortable. Je vous remercie!
42

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

  1. ls /invalid/path && echo "hello!"
    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 répertoire de ce type".
    La seconde moitié de la commande (echo "hello!") N'est jamais exécutée car la première moitié a échoué.

  2. ls /invalid/path ; echo "hello!"
    Le même message d'erreur apparaît comme avant, mais cette fois, la deuxième partie est exécutée !
    ls: / invalid / path: Aucun fichier ou répertoire de ce type
    hello!

Pourquoi est-ce utile?
Supposons que vous souhaitiez extraire un fichier appelé archive.tar.gz.
Vous pouvez 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 tu utilises ; dans la même situation, l'archive est supprimée et vous ne pouvez plus essayer.

Kenny Rasschaert
la source
8

&&is AND, ce qui signifie que la deuxième commande ne sera exécutée que si la première a renvoyé la valeur true (aucune erreur).

Ward Muylaert
la source
1
&& est un "alors" (pas un "et") ... voir ma réponse
Peter.O
2
@fred Je dirais que c'est un "et" avec une évaluation de court-circuit - si la première partie n'est pas vraie, elle sait que le résultat total doit être faux, la seconde partie est donc sautée. Mais convenez que le fait de le considérer comme un "alors" fait rarement une grande différence dans ce contexte.
Jg-Faustus
2
@fred Bien que, sur le plan conceptuel, il soit peut-être plus facile de comprendre ainsi, je ne suis pas d'accord avec votre déclaration. L'idée est simplement que, quelle que soit l'AND exécution, le deuxième paramètre devient inutile si le premier est égal à: falsele code sous-jacent est donc optimisé pour différer l'évaluation du deuxième paramètre jusqu'à ce qu'il sache en quoi consiste le premier.
Ward Muylaert
2
@fred Je ne suis pas sûr de ce que cet exemple tente de faire valoir. &&est juste un opérateur binaire, une fonction. La seule chose "spéciale" est qu’il s’agit de la notation infixe (qui est de toute façon la norme pour la plupart de ces types d’opérateurs) et de l’exécution tardive du second opérande. Cette exécution retardée lui donne en effet la possibilité d’être utilisée de manière conceptuelle comme une ifinstruction dans ce contexte , mais cela n'enlève rien au fait que l’utilisation initialement prévue est dans les conditions d’une ifinstruction réelle . L'utilisation ici est vraiment plus d'un "hack".
Ward Muylaert
3
@fred Bien sûr, ce n'est pas un opérateur ternaire, c'est juste la succession de deux opérations a && b || c = (a && b) || c. Ordre d'évaluation simple. Il n'y a vraiment pas de mystère là-bas. Si vous les écrivez comme vos fonctions typiques, cela ressemblerait simplement à or(and(a, b), c). Cette logique est la même dans un ifconditionnel et lors de son entrée directe dans la ligne de commande car &&et ||sont des opérateurs , ils prennent deux opérandes et en retournent un autre.
Ward Muylaert
8

Mise à jour : j'ai ajouté comme script pour mettre en évidence certains des pièges possibles:

Parce que personne n'a mentionné "||", je vais

Update2 : une reformulation importante ici
&& est comme un "alors" d'une instruction "if" qui répond à "true"

|| n'est pas comme le "else" d'une déclaration "if" ..
|| est comme un "alors" d'une "si" déclaration qui répond à "faux"

Plus précisément, && teste le $? renvoie la valeur de la dernière instruction exécutée précédemment et passe le contrôle à l'instruction ou au sous-shell immédiatement après le && ... il ne transmet 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 ($?) à partir de la dernière instruction exécutée précédemment ... NB! Nota Bene! Notez bien! .... si l'instruction prédecing est une instruction && qui renvoie faux lorsque vous vous attendez à ce qu'elle soit vraie, alors || répondra au faux, donc mélanger les deux sur la même ligne peut être risqué

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

Le test de base et le && et le || déclaration doit tous être sur la même ligne ...


Exécutez ce script pour voir où les problèmes peuvent survenir avec && et ||
La dernière déclaration exécutée peut ne pas être celle que vous attendez.

[[condition]] && echo Hello || echo Au revoir .... est généralement sans danger,
car un écho bien formé retournera vrai.
mais qu'en est-il de l'accès à un fichier qui n'existe pas?

#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR  contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. condition is true" || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. condition is true" || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. condition is true" || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. condition is true" || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. condition is true" && echo  " ((1==1)) rc=$? ..&&.. condition is false"
  $0  0   || echo "  \$0  0   rc=$? ..||.. condition is true" && echo "  \$0  0   rc=$? ..&&.. condition is false"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. condition is true" && echo  " ((1!=1)) rc=$? ..&&.. condition is false"
  $0  1   || echo "  \$0  1   rc=$? ..||.. condition is true" && echo "  \$0  1   rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"

exit 

Peter.O
la source
1

essayer

false && echo "bonjour"

et

faux ; echo "bonjour"

regarde la différence

Petrie Wong
la source
0

La commande (fonction, dans le cas d’un script) après &&est exécutée en fonction du RETVAL de la première commande (fonction, dans le cas d’un script). Cela force la première commande à renvoyer la valeur 0 si elle aboutit. Nous pouvons vérifier la valeur de retour pour exécuter d'autres commandes.

theTuxRacer
la source