76 votes

Quel est le sens d'un! avant une commande dans le shell?

La question est dans le titre. Quel est le but d'une commande shell (une partie d'un script shell) en commençant par un point d'exclamation? Exemple concret:

Dans foo.sh:

#!/usr/bin/env bash
set -e
! docker stop foo
! docker rm -f foo
# ... other stuff

Je sais que sans l'espace le point d'exclamation est utilisé pour l'histoire des remplacements et ! <expression> selon la page de manuel peut être utilisé pour évaluer la "True si expr est faux". Mais dans l'exemple de contexte qui n'a pas de sens pour moi.

80voto

fedorqui Points 42938

TL;DR: C'est seulement par le passage de l' set -e pavillon dans la ligne où vous l'utilisez.


L'ajout d'ajouter à hek2mgl est juste et utile de répondre.

Vous avez:

set -e
! command

Bash Manuel de Référence → Pipelines décrit:

Chaque commande d'un pipeline est exécutée dans son propre shell interne est exécuté. Le statut de sortie d'un pipeline est le statut de sortie de la dernière commande dans le pipeline (...). Si le mot réservé ‘!' précède le pipeline, le statut de sortie est la négation logique de l'état de sortie comme décrit ci-dessus. Le shell attend que toutes les commandes dans le pipeline de la fin avant de retourner une valeur.

Cela signifie qu' ! précédente une commande, c'est dénier le statut de sortie de celui-ci:

$ echo 23
23
$ echo $?
0
                # But
$ ! echo 23
23
$ echo $?
1

Ou:

$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail

Le statut de sortie est utile dans de nombreuses façons. Dans votre script, utilisé conjointement avec d' set -e rend le script de sortie à chaque fois qu'une commande renvoie un état différent de zéro.

Ainsi, lorsque vous aurez:

set -e
command1
command2

Si command1 renvoie un état différent de zéro, le script va finir et de ne pas procéder à l' command2.

Cependant, il est également un point intéressant à mentionner, décrit dans 4.3.1 L'Ensemble Builtin:

-e

Quitter immédiatement si un pipeline (voir les Pipelines), qui peut consister en une simple commande (voir Commandes Simples), une liste (voir Listes), ou un composé de commande (voir Commandes composées) renvoie un état différent de zéro. Le shell n'est pas la sortie si la commande échoue fait partie de la liste des commandes immédiatement après un certain temps ou jusqu'à ce mot-clé, une partie de l'essai dans une instruction if, partie d'une commande exécutée dans un && ou || liste à l'exception de la commande à la suite de la finale && ou ||, toute commande d'un pipeline, mais le dernier, ou si la commande à retour d'état est inversé avec !. Si un composé de commande autre qu'un shell interne est exécuté renvoie une valeur non nulle à cause d'un échec de la commande tout -e a été ignoré, le shell n'est pas la sortie. Un piège sur l'erreur, si elle est définie, est exécuté avant que le shell sorties.


En prenant tous ces facteurs en considération, lorsque vous aurez:

set -e
! command1
command2

Ce que vous faites est de by-pass de l' set -e drapeau dans l' command1. Pourquoi?

  • si command1 fonctionne correctement, il sera de retour à zéro statut. ! va le nier, mais set -e ne sera pas déclencher une sortie par le car elle provient d'un état de retour inversé avec !, comme décrit ci-dessus.
  • si command1 échoue, il renvoie à un état différent de zéro. ! va le nier, de sorte que la ligne sera à la fin de retour à zéro le statut et le script continuera normalement.

24voto

hek2mgl Points 38787

Si vous ne voulez pas que le script échoue dans les deux cas, en cas d'erreur ou de succès de la commande, vous pouvez également utiliser cette alternative:

 set -e
docker stop foo || true
 

La valeur booléenne ou true fait que le pipeline a toujours pour valeur de retour 0 .

1voto

Les K Points 19

"!" Signifie "pas", donc quand vous le placez avant une commande et que vous lancez "$?" Il va faire écho à 1. Ce qui signifie qu’il a échoué au lieu d’un 0, ce qui signifie succès.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X