Le script bash avec `set -e` ne s'arrête pas sur la command` … && … `

J'utilise set -e pour arrêter le script bash lors de la première erreur .

Tout fonctionne correctement sauf si j'utilise la command avec && :

 $ cat script set -e cd not_existing_dir && echo 123 echo "I'm running! =P" $ $ ./script ./script: line 2: cd: not_existing_dir: No such file or directory I'm running! =P $ 

comparé à:

 $ cat script set -e cd not_existing_dir echo "I'm running! =P" $ $ ./script ./script: line 2: cd: not_existing_dir: No such file or directory $ 

Le premier exemple I'm running! fait toujours écho I'm running! , mais le second ne le fait pas. Pourquoi se comportent-ils différemment?

UPD. Question similaire: https://stackoverflow.com/questions/6930295/set-e-and-short-tests

C'est un comportement documenté. La page de manuel bash (1) dit, pour set -e ,

Le shell ne quitte pas si la command qui échoue fait partie de la list de commands immédiatement après un while ou until mot key, partie du test suivant les mots réservés elif ou elif , fasse partie d'une command exécutée dans un && ou || list sauf la command qui suit le && ou || , n'importe quelle command dans un pipeline mais la dernière, ou si la valeur de return de la command est inversée avec ! .
[Je souligne.]

Et la spécification du langage de command du shell POSIX confirme que c'est le comportement correct:

Le paramètre -e doit être ignoré lors de l'exécution de la list composée après le mot while , if , ou elif reserved, un pipeline commençant par le ! mot réservé, ou toute command d'une list AND-OR autre que le dernier.

et la section 2.9.3, les lists de ce document définissent

Une list AND-OR est une séquence d'un ou plusieurs pipelines séparés par les opérateurs " && " et " || ".

L'option set -e n'a pas d'effet dans certaines situations, et il s'agit du comportement standard et portable à travers le shell compatible POSIX.


La command ayant échoué fait partie du pipeline:

 false | true; echo printed 

imprimera printed .

Et seul l'échec du pipeline lui-même est considéré:

 true | false; echo 'not printed' 

n'imprimera rien.


La command échouée s'exécute dans la list composée après le while , until , if , elif mot réservé, un pipeline commençant par le ! mot réservé, ou toute command dans le cadre de && ou || list sauf la dernière:

 false || true; echo printed 

La dernière command échoue set -e : set -e affected:

 true && false; echo 'not printed' 

Le sous-shell échoue dans une command composée:

 (false; echo 'not printed') | cat -; echo printed 

ma conjecture est si-alors la condition dans son set évaluer à vrai.

j'ai essayé

 set -e if cd not_existing_dir then echo 123 fi echo "I'm running! =P" 

qui donne

 -bash: cd: not_existing_dir: No such file or directory I'm running! =P 

le code d'erreur est intercepté par condition si, bash ne triggersra pas la fin de l'exécution.