Comment conserver le dernier statut de sortie après le test

Est-il possible de garder le dernier statut de sortie de la command ( $? ) Inchangé après un test?

Par exemple, je voudrais faire:

 command -p sudo ... [ $? -ne 1 ] && exit $? 

La dernière exit $? devrait renvoyer l'état de sortie sudo, mais renvoie toujours 0 (code de sortie du test).

Est-il possible de le faire sans une variable temporaire?

Un autre exemple pour clarifier davantage:

  spd-say "$@" [ $? -ne 127 ] && exit $? 

Dans ce cas, je ne veux sortir que si la première command est trouvée (code de sortie! = 127 ). Et je veux sortir avec le code de sortie réel spd-say (il ne peut pas être 0 ).

EDIT: J'ai oublié de mentionner que je préfère une solution POSIX-plainte pour une meilleure portabilité.

J'utilise cette construction dans les scripts où je veux fournir des alternatives pour la même command. Par exemple, voir mon script crc32 .

Le problème avec les variables temporaires est qu'elles peuvent masquer d'autres variables, et éviter d'utiliser des noms longs, ce qui n'est pas bon pour la lisibilité du code.

$_ fonctionnera dans (au less) dash interactif, bash , zsh , ksh (mais apparemment pas dans une déclaration conditionnelle comme demandé) et coquilles mksh . De ceux-là, à ma connaissance, seuls bash et zsh le zsh également dans un shell scripté. Ce n'est pas un paramètre POSIX – mais il est assez portable pour n'importe quel shell moderne et interactif.

Pour une solution plus portable, vous pouvez faire:

 command -p sudo ... eval '[ "$?" = 127 ] || exit '"$?" 

Qui vous permet essentiellement d'étendre la valeur initiale de $? dans la queue du script avant même de tester sa valeur à sa tête.

Mais de toute façon, puisque vous semblez tester si la command sudo peut être trouvée dans la string de path d'access portable embeddede du shell avec la command , je pense que vous pourriez y aller un peu plus directement. De plus, pour être clair, la command ne testera pas l'location des arguments vers sudo – donc ce n'est que sudo – et rien ne l'invoque – qui est pertinent pour cette valeur de return.

Et donc de toute façon, si c'est ce que vous essayez de faire:

 command -pv sudo >/dev/null || handle_it command -p sudo something or another 

… fonctionnerait bien comme un test sans risque d'erreur dans la command sudo s'exécute de manière à biaiser les résultats de votre test.

Il existe différentes options pour gérer l'état de sortie de manière fiable sans surcharge, en fonction des besoins réels.

Vous pouvez save l'état de sortie à l'aide d'une variable:

 command -p sudo ... rc=$? [ "$rc" -ne 1 ] && echo "$rc" 

Vous pouvez vérifier directement le succès ou l'échec:

 if command -p sudo ... then echo success else echo failure fi 

Ou utilisez une construction de case pour différencier l'état de sortie:

 command -p sudo ... case $? in (1) ... ;; (127) ... ;; (*) echo $? ;; esac 

avec le cas spécial posé dans la question:

 command -p sudo ... case $? in (1) :;; (*) echo $?;; esac 

Toutes ces options ont l'avantage de se conformer à la norme POSIX.

(Note: Pour l'illustration, j'ai utilisé echo commands echo ci-dessus, remplacées par des instructions de exit appropriées pour correspondre à la fonction demandée.)

 command -p ... test 1 -ne $? && exit $_ 

Utilisez $_ , qui s'étend au dernier argument de la command précédente.

Vous pouvez définir (et utiliser) une fonction shell:

 check_exit_status() { [ "$1" -ne 1 ] && exit "$1" } 

alors

 command -p sudo ... check_exit_status "$?" 

On peut soutenir que c'est "sortingcher", puisqu'il fait une copy de $? dans la list d'arguments check_exit_status .

Cela peut sembler un peu gênant, et c'est le cas. (Cela arrive parfois lorsque vous imposez des contraintes arbitraires aux problèmes.) Cela peut sembler inflexible, mais ce n'est pas le cas. Vous pouvez rendre check_exit_status plus complexe, en ajoutant des arguments qui lui indiquent quel (s) test (s) faire sur la valeur de statut de sortie.

Pour répondre à votre question directe, non, il n'est pas possible de garder $? inchangé. Et c'est un de ces cas où je soupçonne que vous vous concentrez sur le mauvais problème. Une variable temporaire est la manière standard et préférée d'get l'effet que vous searchz. C'est tellement standard que je suggère d'abandonner (ou de repenser) quelque raison que vous pensez que vous avez pour ne pas vouloir en utiliser un; Je doute fort que cela vaille la complexité supplémentaire ajoutée par n'importe quelle autre méthode.

Si vous requestz simplement par simple curiosité, alors la réponse est non.

Voici mon extrait de code pour conserver un statut de sortie précédent sans quitter le script / shell actuel

 EXIT_STATUS=1 if [[ $EXIT_STATUS == 0 ]] then echo yes else (exit $EXIT_STATUS) fi