Lequel est le meilleur: utiliser; ou && pour exécuter plusieurs commandes sur une seule ligne?

429

Dans les tutoriels et les procédures, je vois souvent des commandes combinées. Par exemple,

sudo apt-get update && sudo apt-get install pyrenamer

Il semble y avoir quatre connecteurs possibles: &, &&, ||et ;. Bien que le & connecteur soit clair pour moi (il envoie un processus à l’arrière-plan et laisse le terminal disponible), la différence entre &&et ;. Et je ne savais rien ||avant le commentaire de Kaya.

Les questions suivantes traitent de la différence entre les deux connecteurs, mais le font principalement dans les commentaires:

Donc, voici un certain nombre de questions connexes:

  1. Et quelle est la différence entre ;et &&?
  2. Quand devriez-vous les utiliser respectivement? Il serait bien de voir quelques cas d’utilisation: si je veux exécuter une commande puis éteindre mon ordinateur, quel connecteur devrais-je choisir?
  3. Quels sont leurs avantages et leurs dangers ? Robie Basak mentionne dans un commentaire à cette réponse qu'une commande semblable à, par exemple, cd /somewhere_else; rm -Rf *peut avoir des conséquences destructives si le premier élément de la chaîne de commande échoue.
  4. Si pertinent, d'où viennent-ils?
don.joey
la source
7
Il existe un autre connecteur que vous n'avez peut-être pas rencontré: il ||est identique &&à celui-ci, sauf qu'il n'exécute la deuxième commande que si la première a quitté avec un statut non nul (échec).
Kaya
4
Notez également que l'exécution de votre script avec set -earrêtera le script en cas d'échec, comme si toutes les commandes étaient connectées &&.
Choroba
stackoverflow.com/questions/3573742/…
Ciro Santilli a reçu une note
3
Personne n'a répondu à Qn 4 ... Je soupçonne le comportement de && et || a été inspiré par le langage de programmation C. Dans le cas de (x && y), si x est évalué à false, l'expression entière doit être false pour qu'un compilateur puisse optimiser l'évaluation de y, au cas où cela coûterait cher. Les normes C et C ++ modernes exigent en réalité cette optimisation. Les programmes peuvent donc supposer en toute sécurité que y ne sera pas évalué si x est faux. Par exemple, (ptr && ptr-> days> 31) ne plantera pas même si ptr est null. Également en C, les déclarations se terminent par; indépendamment de savoir s'il y a une autre déclaration sur la même ligne ou non.
Kevin

Réponses:

775

Cheatsheet:

A; B    # Run A and then B, regardless of success of A
A && B  # Run B if and only if A succeeded
A || B  # Run B if and only if A failed
A &     # Run A in background.
Jack
la source
19
Et bien sûr, A & B &exécutez A en arrière-plan, puis B en arrière-plan (quel que soit votre succès) et renvoyez le contrôle au shell. Cela fonctionne souvent à peu près comme si vous exécutiez les deux processus en même temps.
Expiation limitée
4
est-il possible de dire: exécuter a en arrière-plan, suivi de b en arrière-plan uniquement si a travaillé? (Je suppose &&&??)
utilisateur230910
15
@ user230910: ce serait (A && B) &.
leftaroundabout
5
Pouvez-vous vous référer à un document faisant autorité pour cela?.
Jaime Hablutzel
@ Jack Lorsque exécuté à partir de Cronjob, il ne suit pas très bien cette règle, vous ne savez pas pourquoi? Pour un fichier python
CodeGuru
77

&&exécute la deuxième commande uniquement si la première est sortie avec le statut 0 (a réussi). ;exécute les deux commandes, même si la première sort avec un statut différent de zéro.

Votre exemple avec &&peut être paraphrasé de la manière suivante:

if sudo apt-get update ; then
    sudo apt-get install pyrenamer
fi
choroba
la source
Merci. J'ai mis à jour la question pour m'assurer que les différentes sous-questions se distinguent facilement.
don.joey
5
@Private: vous devez utiliser ;si la deuxième commande n'a pas besoin de la précédente pour réussir.
Choroba
31

Utiliser ;exécutera les commandes, que la première commande soit réussie ou non.

utiliser &&execute 2nd command uniquement lorsque la première commande a été exécutée avec succès (état 0).

Les deux sont utilisés sur des perspectives différentes. Comme pour un processus plus long, disons que pour une installation, vous devez le compiler et l'installer. vous devriez make && make install. Donc, l'installation ne fonctionnera qu'en cas de makesuccès.

Donc, pour les commandes dépendantes, vous devriez utiliser &&

Wring bash, ou des commandes avec des commandes indépendantes utilisent ;

Donc , si vous voulez éteindre l' ordinateur même le premier emploi utilisation échoué ;, mais si besoin le succès du premier emploi initier l'utilisation d'arrêt&&

Web-E
la source
14

a ; bs'exécutera b quel que soit le statut de sortie de a. a && bse déroulera b que si a réussi.

Ceci est nécessaire et suffisant pour répondre aux 3 premières questions. En particulier, le 2 est trop large et ne peut pas donner "une" réponse définitive - votre meilleur pari est de décider au cas par cas.

En ce qui concerne la 4ème question: Ce sont la syntaxe Bash .

Il n'y a pas de danger intrinsèque à utiliser non plus. Encore une fois, la définition ci-dessus est suffisante. Cela implique que vous écriviez &&quand ba des effets involontaires si ane réussit pas. Il n'y a pas besoin de règles ou d'explications supplémentaires, à mon humble avis.

Ignis
la source
1

UNE; B # Exécuter A puis B, quel que soit le succès de A

A && B # Exécuter B si et seulement si A réussit

A || B # Exécuter B si et seulement si A échoue

A & # Run A en arrière-plan.

Une très bonne règle de base. J'ajouterais que dans certains cas, l'utilisation de ces commandes dans un sous-shell a du sens si nous voulons les considérer comme une seule unité ou si nous ne voulons pas coupler certains résultats d'opérations au shell actuel.

Exemples:

-concatenate la sortie de deux commandes:

(ls foo; ls bar) > single-result.txt

- aller dans un répertoire et exécuter une commande à partir de là sans changer le répertoire en cours du shell:

(cd target-directory && jar -xf ../my-jar)
davidxxx
la source