Apprenez en lisant dans l'ordre

Script Shell - Arguments et codes de sortie

Récupère les valeurs de ./a.sh foo bar avec $1 $2 $@ $# $0, fournis un défaut avec ${2:--}, vérifie $? et renvoie succès ou échec avec exit 0 / exit 1 — écris et exécute un script pratique, illustré dans un terminal en navigateur.

Récupérer les arguments — $1 / $2 / $0

Les scripts peuvent recevoir des valeurs quand tu les exécutes.

Les valeurs que tu listes après la commande, comme ./a.sh foo bar, sont appelées des arguments, et dans le script $1 est le premier et $2 le deuxième.

$0 est le nom du script lui-même, $# est le nombre d'arguments passés, et $@ représente tous les arguments ensemble.

Grâce à eux, tu peux exécuter le script avec une entrée différente à chaque fois au lieu de valeurs fixes.

SyntaxeSignificationExemple
$1 $2Premier et deuxième argumentsecho "$1 then $2"
$0Le nom du script lui-mêmeecho "running $0"
$#Nombre d'arguments passésecho "argc=$#"
$@Tous les arguments ensembleecho "all: $@"
La correspondance des arguments
./a.sh foo bar$1 = foo$2 = bar$# = 2$@ = foo bar1er2enombretout
Les valeurs que tu passes vont dans $1 $2 ; $# donne le nombre et $@ l'ensemble complet.
set -- foo bar                   # définit les paramètres positionnels pour la démo
echo "1st: $1"                   # foo
echo "2nd: $2"                   # bar
echo "argc: $#"                  # 2
echo "all: $@"                   # foo bar

Écris un script qui reçoit des valeurs comme arguments et les affiche telles quelles.

① Ouvre args.sh avec vi args.sh, appuie sur i pour passer en mode insertion, et mets #!/bin/sh sur la première ligne.

② Écris du code qui affiche le premier argument ($1), le deuxième ($2), le nombre ($#), tous les arguments ($@) et le nom du script ($0).

③ Appuie sur Esc, enregistre avec :wq, puis ajoute la permission d'exécution.

④ Exécute-le avec ./args.sh foo bar avec deux arguments et vérifie quelle valeur est entrée dans quelle variable. Si tu bloques, copie le corps depuis le panneau de réponse et colle-le dans le mode insertion de vi. (Exécute-le correctement et l'explication apparaîtra.)

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

Fournir un défaut — ${1:-def}

Parfois aucun argument n'est passé.

Si tu écris ${1:-default}, default est utilisé quand $1 n'est pas défini ou est vide, et la valeur fournie est utilisée quand il y en a une.

Cela te permet d'écrire un script qui suit l'argument quand il est fourni, et fonctionne avec un défaut sûr quand il ne l'est pas.

Vérifier $# te dit aussi si le nombre attendu d'arguments est bien arrivé.

SyntaxeSignificationExemple
${1:-def}Utilise def quand $1 n'est pas défininame=${1:-guest}
${2:-def}Utilise def quand $2 n'est pas définisep=${2:--}
Comment le défaut est fourni
sep=${2:--}$2 = barsep = bar$2 est videsep = - (défaut)si fournisi omisTel que fourniUtilise le défaut
Avec ${2:--}, passer une deuxième valeur l'utilise, et l'omettre utilise le défaut -.
set --                           # reproduit une exécution sans argument
echo "${1:-guest}"               # non défini, donc guest
set -- alice                     # maintenant le premier argument est défini
echo "${1:-guest}"               # a une valeur, donc alice

Écris un script qui reçoit un séparateur comme argument et utilise un défaut quand il est omis.

① Ouvre format.sh avec vi format.sh, appuie sur i pour passer en mode insertion, et mets #!/bin/sh sur la première ligne.

② Reçois le premier argument comme nom de cible et le deuxième comme séparateur, mais écris-le avec ${2:-...} pour qu'un défaut (par exemple -) soit utilisé quand le deuxième manque, puis affiche la cible et le séparateur.

③ Appuie sur Esc, enregistre avec :wq, puis ajoute la permission d'exécution.

④ Exécute d'abord ./format.sh foo, en omettant le deuxième argument, et vérifie que le séparateur retombe sur le défaut. Si tu bloques, copie le corps depuis le panneau de réponse et colle-le dans le mode insertion de vi.

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

Renvoyer succès ou échec — $? et exit N

Quand une commande se termine, elle renvoie un code de sortie, un nombre de 0 à 255.

Par convention 0 signifie succès et tout autre que 0 signifie échec.

Tu peux lire le code de sortie de la commande précédente avec $?.

Pour grep c'est 0 quand c'est trouvé et 1 quand ça ne l'est pas, donc la valeur change selon le résultat.

Depuis l'intérieur d'un script, tu définis le code de sortie explicitement avec exit N.

Renvoyer exit 0 pour le succès et exit 1 pour l'échec est la convention courante.

L'appelant reçoit cette valeur via $? ou && || et peut l'utiliser pour le contrôle, par exemple avancer seulement en cas de succès.

Si tu omets exit, le code de sortie de la dernière commande exécutée est renvoyé tel quel.

SyntaxeSignificationExemple
$?Code de sortie de la commande précédentegrep x f; echo $?
exit NTermine le script avec le code de sortie Nexit 1
Le flux des codes de sortie
Le traitement réussitexit 0$? = 0Le traitement échoueexit 1$? = 1renvoielitrenvoielitSuccèsÉchec
Un script renvoie exit 0 en cas de succès et exit 1 en cas d'échec, et l'appelant lit le résultat avec $?.
printf 'apple\nbanana\n' > fruits.txt   # crée le matériel
grep apple fruits.txt > /dev/null
echo "found? $?"                          # trouvé, donc 0
grep mango fruits.txt > /dev/null
echo "found? $?"                          # non trouvé, donc 1

Écris un script qui cherche dans un fichier un mot donné en argument et renvoie un code de sortie selon le résultat.

① Ouvre search.sh avec vi search.sh, appuie sur i pour passer en mode insertion, et mets #!/bin/sh sur la première ligne.

② Dans le script, crée un fichier de matériel et cherches-y le mot reçu comme premier argument. Écris du code qui affiche un message de succès et renvoie exit 0 quand c'est trouvé, ou affiche un message d'échec et renvoie exit 1 quand ça ne l'est pas.

③ Appuie sur Esc, enregistre avec :wq, puis ajoute la permission d'exécution.

④ Exécute-le avec ./search.sh foo bar, puis vérifie le code de sortie avec echo $?. Si tu bloques, copie le corps depuis le panneau de réponse et colle-le dans le mode insertion de vi.

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

Traiter chaque argument à tour de rôle — $@ et $#

Quand le nombre d'arguments n'est pas fixe, au lieu d'écrire $1 $2 un par un, parcours $@ avec for pour en traiter autant qu'il en a été passé.

La forme for x in "$@"; do … done les prend un à la fois, et afficher le nombre avec $# permet au même script de gérer n'importe quel nombre d'arguments.

C'est un motif courant dans les outils qui traitent plusieurs fichiers ensemble.

SyntaxeSignificationExemple
"$@"Passe chaque argument un mot à la fois (pour for ; nécessite des guillemets doubles)for x in "$@"; do
$#Nombre d'arguments passésecho "count=$#"
Boucler sur tous les arguments
./a.sh foo bar baz$# = 3$@ = foo bar bazfor x in "$@"- foo- bar- baznombretoutun par unafficheboucle avec for
Obtiens le nombre avec $#, puis prends chaque argument un à la fois avec $@ dans une boucle for pour les traiter.
set -- foo bar baz               # définit les paramètres positionnels pour la démo
echo "argc: $#"                  # 3
for x in "$@"; do
  echo "- $x"                    # - foo / - bar / - baz
done

Écris un script qui traite chaque argument passé un à la fois et affiche aussi le nombre.

① Ouvre list.sh avec vi list.sh, appuie sur i pour passer en mode insertion, et mets #!/bin/sh sur la première ligne.

② Affiche le nombre d'arguments avec $#, puis prends chacun à tour de rôle avec $@ dans une boucle for et affiche chaque argument sur sa propre ligne.

③ Appuie sur Esc, enregistre avec :wq, puis ajoute la permission d'exécution.

④ Exécute-le avec ./list.sh foo bar baz avec trois arguments et vérifie que le nombre et chaque argument s'affichent dans l'ordre. Si tu bloques, copie le corps depuis le panneau de réponse et colle-le dans le mode insertion de vi.

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Qu'est-ce qui entre dans $2 quand tu exécutes ./a.sh foo bar ?

Question 2Quelle est la bonne signification de ${1:-guest} ?

Question 3Lequel lit le code de sortie qui indique si la commande précédente a réussi ?