Utilisées proprement, les variables peuvent ajouter puissance et flexibilité à vos scripts. Ceci nécessite l'apprentissage de leurs subtilités et de leurs nuances.
Variables affectant le comportement des scripts bash.
Le chemin vers le binaire Bash.
bash$ echo $BASH /bin/bash
Variable d'environnement pointant vers un script Bash de démarrage lu lorsqu'un script est invoqué.
Variable indiquant le niveau du sous-shell. C'est un nouvel ajout de Bash, version 3.
Voir l'Exemple 20.1, « Étendue des variables dans un sous-shell » pour son utilisation.
numéro de processus de l'instance courante de Bash. Cette variable n'ets pas identique à $$ mais elle donne souvent le même résultat.
bash4$ echo $$ 11015 bash4$ echo $BASHPID 11015 bash4$ ps ax | grep bash4 11015 pts/2 R 0:00 bash4
#!/bin/bash4 echo "\$\$ à l'extérieur du sous-shell = $$" # 9602 echo "\$BASH_SUBSHELL à l'extérieur du sous-shell = $BASH_SUBSHELL" # 0 echo "\$BASHPID à l'extérieur du sous-shell = $BASHPID" # 9602 echo ( echo "\$\$ à l'intérieur du sous-shell = $$" # 9602 echo "\$BASH_SUBSHELL à l'intérieur du sous-shell = $BASH_SUBSHELL" # 1 echo "\$BASHPID à l'intérieur du sous-shell = $BASHPID" ) # 9603 # Remarque : $$ fournit le PID du processus parent.
Tableau à six éléments contenant des informations sur la version installée de Bash. Cette variable est similaire à $BASH_VERSION, ci-dessous, mais en un peu plus détaillé.
# Infos sur la version de Bash : for n in 0 1 2 3 4 5 do echo "BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}" done # BASH_VERSINFO[0] = 3 # No majeur de version. # BASH_VERSINFO[1] = 00 # No mineur de version. # BASH_VERSINFO[2] = 14 # Niveau de correctifs. # BASH_VERSINFO[3] = 1 # Version construite. # BASH_VERSINFO[4] = release # État de la version. # BASH_VERSINFO[5] = i386-redhat-linux-gnu # Architecture. # (identique à $MACHTYPE).
La version de Bash installée sur le système.
bash$ echo $BASH_VERSION 3.2.25(1)-release
tcsh% echo $BASH_VERSION BASH_VERSION: Undefined variable.
Vérifier $BASH_VERSION est une bonne méthode pour déterminer le shell qui est en cours d'exécution. $SHELL ne donne pas nécessairement la bonne réponse.
La valeur du dessus de la pile de répertoires [34] (affectée par pushd et popd)
Cette variable intégrée correspond à la commande dirs. Néanmoins, dirs affiche le contenu entier de la pile de répertoires.
L'éditeur appelé par défaut par les scripts, en général vi ou emacs.
Numéro d'identifiant « effectif » de l'utilisateur.
Numéro d'identification, quelle que soit l'identité que l'utilisateur actuel assume, peut-être suite à un su.
$EUID n'est pas nécessairement le même que $UID.
Le nom de la fonction en cours d'exécution.
xyz23 () { echo "$FUNCNAME en cours d'exécution." # xyz23 en cours d'exécution. } xyz23 echo "FUNCNAME = $FUNCNAME" # FUNCNAME = # vide en dehors d'une fonction
See also Exemple A.50, « Autre version du script getopt-simple.sh ».
Une liste de modèles de noms de fichiers à exclure de la correspondance lors d'un remplacement.
Les groupes auxquels l'utilisateur appartient.
C'est une liste (de type tableau) des numéros d'identifiant de groupes pour l'utilisateur actuel, identique à celle qui est enregistrée dans des fichiers /etc/passwd et /etc/group.
root# echo $GROUPS 0 root# echo ${GROUPS[1]} 1 root# echo ${GROUPS[5]} 6
Répertoire personnel de l'utilisateur, en général /home/utilisateur (voir l'Exemple 9.16, « Utiliser la substitution et les messages d'erreur »)
La commande hostname définit le nom de l'hôte au démarrage en utilisant un script de démarrage. Néanmoins, la fonction gethostname() initialise la variable interne Bash $HOSTNAME. Voir aussi l'Exemple 9.16, « Utiliser la substitution et les messages d'erreur ».
Type de l'hôte.
Comme $MACHTYPE, identifie le matériel du système.
bash$ echo $HOSTTYPE i686
Séparateur interne du champ de saisie.
Cette variable détermine la façon dont Bash reconnaît les champs ou les limites de mots lorsqu'il interprète des chaînes de caractères.
La valeur par défaut de $IFS est un blanc (espace, tabulation et retour chariot) mais peut être changé, par exemple, pour analyser un fichier de données séparées par des virgules. Notez que $* utilise le premier caractère contenu dans $IFS. Voir l'Exemple 5.1, « Afficher des variables bizarres ».
bash$ echo "$IFS" (Avec la valeur par défaut de $IFS, une ligne blanche apparaît.) bash$ echo "$IFS" | cat -vte ^I$ $ (Affiche un blanc : une espace, ^I [tabulation horizontale], ou un retour chariot, et un dollar ($) en fin de ligne.) bash$ bash -c 'set w x y z; IFS=":-;"; echo "$*"' w:x:y:z (Lit les commandes à partir de la chaîne et affecte tout argument suivant les paramètres de position)
(Merci beaucoup, Stéphane Chazelas, pour cette clarification et les exemples ci-dessus.)
Voir aussi l'Exemple 15.41, « Analyser le domaine d'un courrier indésirable » , Exemple 10.7, « Un remplaçant de grep pour les fichiers binaires » et Exemple 18.14, « Analyser une boîte mail » pour des exemples instructifs sur l'utilisation de $IFS.
Ignore EOF : nombre de fins de fichier (control-D) que le shell va ignorer avant de déconnecter.
Souvent intégré dans les fichiers .bashrc ou /etc/profile, cette variable contrôle l'ordre d'examen dans l'expansion des noms de fichiers et les correspondances de modèles. Si elle est mal gérée, LC_COLLATE peut apporter des résultats inattendus dans le remplacement de noms de fichiers.
À partir de la version 2.05 de Bash, le remplacement de noms de fichiers ne tient plus compte des lettres en minuscules et en majuscules dans une suite de caractères entre crochets. Par exemple, ls [A-M]* correspondrait à la fois à Fichier1.txt et à fichier1.txt. Pour annuler le comportement personnalisé de la correspondance par crochets, initialisez LC_COLLATE à C par un export LC_COLLATE=C dans /etc/profile et/ou ~/.bashrc.
Cette variable interne contrôle l'interprétation des caractères pour le remplacement et la correspondance de modèles.
Cette variable correspond au numéro de ligne du script shell dans lequel cette variable apparaît. Elle n'a une signification que dans le script où elle apparait et est surtout utilisée dans les phases de débogage.
# *** DEBUT BLOC DEBUG *** dernier_argument_command=$_ # Le sauver. echo "À la ligne numéro $LINENO, la variable \"v1\" = $v1" echo "Dernier argument de la ligne exécutée = $dernier_argument_command" # *** FIN BLOC DEBUG ***
Type de machine.
Identifie le matériel du système.
bash$ echo $MACHTYPE i686
Ancien répertoire courant (« OLD-Print-Working-Directory », le dernier répertoire où vous étiez).
Type de système d'exploitation.
bash$ echo $OSTYPE linux
Chemin vers les binaires, habituellement /usr/bin/, /usr/X11R6/bin/, /usr/local/bin, etc.
Lorsqu'une commande est donnée, le shell recherche automatiquement l'exécutable dans les répertoires listés dans le chemin. Le chemin est stocké dans la variable d'environnement, $PATH, une liste des répertoires, séparés par le symbole ":". Normalement, le système enregistre la définition de $PATH dans /etc/profile et/ou ~/.bashrc (voir l'Annexe G, Fichiers importants)
bash$ echo $PATH /bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/sbin:/usr/sbin
PATH=${PATH}:/opt/bin ajoute le répertoire /opt/bin au chemin actuel. Dans un script, il peut être avantageux d'ajouter temporairement un répertoire au chemin de cette façon. Lorsque le script se termine, le $PATH original est restauré (un processus fils, tel qu'un script, ne peut pas changer l'environnement du processus père, le shell).
Le « répertoire » courant, ./, est habituellement omis de $PATH pour des raisons de sécurité.
Variable de type tableau contenant le(s) code(s) de sortie de la dernière commande en premier plan exécutée via un tube.
bash$ echo $PIPESTATUS 0 bash$ ls -al | bogus_command bash: bogus_command: command not found bash$ echo ${PIPESTATUS[1]} 127 bash$ ls -al | bogus_command bash: bogus_command: command not found bash$ echo $? 127
Les membres du tableau $PIPESTATUS contiennent le code de sortie de chaque commande respective exécutée via un tube. $PIPESTATUS[0] contient le code de sortie de la première commande du tube, $PIPESTATUS[1] le code de sortie de la deuxième commande et ainsi de suite.
La variable $PIPESTATUS peut contenir une valeur 0 erronée dans un shell de connexion (dans les versions précédant la 3.0 de Bash).
tcsh% bash bash$ who | grep nobody | sort bash$ echo ${PIPESTATUS[*]} 0
Les lignes ci-dessus contenues dans un script produiraient le résultat attendu, 0 1 0.
Merci, Wayne Pollock pour avoir partagé ceci en apportant l'exemple ci-dessus.
La variable $PIPESTATUS donne des résultats inattendus dans certains contextes.
bash$ echo $BASH_VERSION 3.00.14(1)-release bash$ $ ls | commande_boguee | wc bash: commande_boguee: command not found 0 0 0 bash$ echo ${PIPESTATUS[@]} 141 127 0
Chet Ramey attribue l'affichage ci-dessus au comportement de ls. Si ls écrit dans un tube dont la sortie n'est pas lue, alors SIGPIPE le tue et son code de sortie est 141. Sinon, son code de sortie est 0, comme attendu. C'est certainement le cas pour tr.
$PIPESTATUS est une variable « volatile ». Elle doit être immédiatement capturée après le tube, c'est-à-dire avant que d'autres commandes n'interviennent.
bash$ $ ls | commande_boguee | wc bash: commande_boguee: command not found 0 0 0 bash$ echo ${PIPESTATUS[@]} 0 127 0 bash$ echo ${PIPESTATUS[@]} 0
L'option pipefail pourrait être utile dans les cas où $PIPESTATUS ne donne pas l'information désirée.
Le $PPID d'un processus est l'identifiant du processus (PID) père. [35]
Comparez ceci avec la commande pidof.
Une variable contenant une commande à exécuter juste avant l'affichage de l'invite principale, $PS1.
Ceci est l'invite principale, vue sur la ligne de commande.
La deuxième invite, vue lorsqu'une saisie supplémentaire est attendue. Elle s'affiche comme « > ».
La troisième invite, affichée lors d'une boucle select (voir l'Exemple 10.29, « Créer des menus en utilisant select »)
La quatrième invite, affichée au début de chaque ligne d'affichage lorsqu'un script a été appelé avec l'option -x. Elle affiche un « + ».
Répertoire courant (répertoire où vous êtes actuellement)
Ceci est analogue à la commande intégrée pwd.
&wipedir;
La variable par défaut lorsqu'aucune n'est adjointe au read. Aussi applicable au menu select, mais renvoie seulement le numéro de l'élément de la variable choisie et non pas la valeur de la variable elle-même.
&reply;
Le nombre de secondes pris par l'exécution du script.
&seconds;
La liste des options activées du shell, variable en lecture seule.
bash$ echo $SHELLOPTS braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs
Niveau du shell, à quel point Bash est imbriqué. [36] Si, à la ligne de commande, $SHLVL vaut 1, alors dans un script, il sera incrémenté et prendra la valeur 2.
Cette variable n'est pas affectée par les sous-shells. Utilisez $BASH_SUBSHELL quand vous avez besoin d'une indication d'une imbrication de sous-shell.
Si la variable d'environnement $TMOUT est initialisée à une valeur différente de zéro appelée time, alors l'invite shell dépassera son délai au bout de time secondes. Ceci causera une déconnexion.
À partir de la version 2.05b de Bash, il est possible d'utiliser $TMOUT dans un script avec un read.
# Fonctionne avec des scripts pour Bash, versions #+ 2.05b et ultérieures. TMOUT=3 # L'invite s'arrête dans trois secondes. echo "Quelle est votre chanson favorite?" echo "Faites vite car vous n'avez que $TMOUT secondes pour répondre !" read chanson if [ -z "$chanson" ] then chanson="(sans réponse)" # Réponse par défaut. fi echo "Votre chanson favorite est $chanson."
Il existe d'autres façons, plus complexes, pour implémenter une entrée avec temporisation. Une alternative consiste à configurer une boucle rythmée pour signaler au script la fin de l'attente. Ceci requiert aussi une routine de gestion du signal pour récupérer (voir l'Exemple 29.5, « Récupérer la sortie ») l'interruption créée par la boucle.
Une autre méthode est d'utiliser stty.
Peut-être que la méthode la plus simple est d'utiliser l'option -t de read.
Numéro de l'identifiant utilisateur.
Numéro d'identification de l'utilisateur actuel, tel qu'enregistré dans /etc/passwd .
C'est l'identifiant réel de l'utilisateur actuel, même s'il a temporairement endossé une autre identité avec su. $UID est une variable en lecture seule, non sujette au changement à partir de la ligne de commande ou à l'intérieur d'un script, et est la contrepartie de l'intégré id.
Voir aussi l'Exemple 2.3, « cleanup : Une version améliorée et généralisée des scripts précédents ».
Les variables $ENV, $LOGNAME, $MAIL, $TERM, $USER et $USERNAME ne sont pas des variables intégrées à Bash. Néanmoins, elles sont souvent initialisées comme variables d'environnement dans un des fichiers de démarrage de Bash. $SHELL, le nom du shell de connexion de l'utilisateur, peut être configuré à partir de /etc/passwd ou dans un script d'« initialisation », et ce n'est pas une variable intégrée à Bash.
tcsh% echo $LOGNAME bozo tcsh% echo $SHELL /bin/tcsh tcsh% echo $TERM rxvt bash$ echo $LOGNAME bozo bash$ echo $SHELL /bin/tcsh bash$ echo $TERM rxvt
Paramètres de position
Paramètres de position passés par la ligne de commande à un script, ou passés à une fonction, ou attribués (set) à une variable (voir l'Exemple 4.5, « Paramètres positionnels » et l'Exemple 14.16, « Utiliser set avec les paramètres de position »)
Nombre d'arguments sur la ligne de commande [37] ou de paramètres de position (voir l'Exemple 33.2, « Un script d'appel légèrement plus complexe »)
Tous les paramètres de position, vus comme un seul mot.
"$*" doit être entre guillemets.
Identique à $*, mais chaque paramètre est une chaîne entre guillemets, c'est-à-dire que les paramètres sont passés de manière intacte, sans interprétation ou expansion. Ceci signifie, entre autres choses, que chaque paramètre dans la liste d'arguments est vu comme un mot séparé.
Bien sûr, "$@" doit être entre guillemets.
Suite à un shift, $@ contient le reste des paramètres de la ligne de commande, sans le $1 précédent qui a été perdu.
#!/bin/bash # Appelé avec ./script 1 2 3 4 5 echo "$@" # 1 2 3 4 5 shift echo "$@" # 2 3 4 5 shift echo "$@" # 3 4 5 # Chaque "shift" perd le paramètre $1. # "$@" contient alors le reste des paramètres.
Le paramètre spécial $@ trouve son utilité comme outil pour filtrer l'entrée des scripts shell. La construction cat "$@" accepte l'entrée dans un script soit à partir de stdin, soit à partir de fichiers donnés en paramètre du script. Voir l'Exemple 15.24, « rot13 : rot13, cryptage ultra-faible. » et l'Exemple 15.25, « Générer des énigmes « Crypto-Citations » ».
Les paramètres $* et $@ affichent quelque fois un comportement incohérent et bizarre, suivant la configuration de $IFS.
Les paramètres $@ et $* diffèrent seulement lorsqu'ils sont entre guillemets.
Autres paramètres spéciaux
Les options passées au script (en utilisant set). Voir l'Exemple 14.16, « Utiliser set avec les paramètres de position ».
Ceci était originellement une construction de ksh adoptée dans Bash et, malheureusement, elle ne semble pas fonctionner de façon fiable dans les scripts Bash. Une utilité possible pour ceci est d'avoir un script testant lui-même s'il est interactif.
Identifiant du processus (PID) du dernier job ayant fonctionné en tâche de fond.
TRACE=$0.log COMMANDE1="sleep 100" echo "Trace des PID des commandes en tâche de fond pour le script : $0" >> "$TRACE" # Pour qu'ils soient enregistrés et tués si nécessaire. echo >> "$TRACE" # Commandes de trace. echo -n "PID de \"$COMMANDE1\" : " >> "$TRACE" ${COMMANDE1} & echo $! >> "$TRACE" # PID de "sleep 100" : 1506 # Merci, Jacques Lederer, pour cette suggestion.
Utiliser $! pour contrôler un job :
job_qui_peut_se_bloquer & { sleep ${TIMEOUT}; eval 'kill -9 $!' &> /dev/null; } # Force la fin d'un programme qui se comporte mal. # Utile, par exemple, dans les scripts d'initialisation. # Merci, Sylvain Fourmanoit, pour cette utilisation ingénieuse de la variable "!".
Ou autrement :
# Exemple de Matthew Sage. # Utilisé avec sa permission. DELAI=30 # Délai d'attente en secondes nombre=0 job_qui_peut_se_bloquer & { while ((nombre < DELAI )); do eval '[ ! -d "/proc/$!" ] && ((count = TIMEOUT))' # /proc est l'endroit où sont disponibles des informations #+ sur les processus en cours d'exécution. # "-d" teste si le répertoire existe. # Donc, nous attendons que le job en question se manifeste. ((nombre++)) sleep 1 done eval '[ -d "/proc/$!" ] && kill -15 $!' # Si le job est en cours d'exécution, tuons-le. }
Variable spéciale portant l'argument final de la dernière commande exécutée.
Exemple 9.9. Variable tiret bas
#!/bin/bash echo $_ # /bin/bash # Simple appel de /bin/bash pour lancer ce script. # Remarque : des variations sont ici possibles, #+ selon la manière dont le script est appelé. du >/dev/null # Donc pas de sortie des commandes echo $_ # du ls -al >/dev/null # Donc pas de sortie des commandes echo $_ # -al (dernier argument) : echo $_ # :
Code de sortie d'une commande, d'une fonction ou du script lui-même (voir l'Exemple 23.7, « Maximum de deux nombres »)
Identifiant (PID) du processus du script lui-même. [38] La variable $$ est souvent employée dans les scripts pour construire des noms de fichiers temporaires « uniques » (voir l'Exemple 29.6, « Nettoyage après un Control-C », l'Exemple 15.31, « Déballer une archive rpm », et l'Exemple 14.27, « Un script qui se tue lui-même »). Ceci est généralement plus simple que d'appeler mktemp.
[34] A stack register is a set of consecutive memory locations, such that the values stored (pushed) are retrieved (popped) in reverse order. The last value stored is the first retrieved. This is sometimes called a LIFO (last-in-first-out) or pushdown stack.
[35] Le PID du script en cours est $$, bien sûr.
[36] Un peu analogue à la récursion, dans ce contexte, l'imbrication réfère à un modèle embarqué à l'intérieur d'un modèle plus large. Une des définitions de nest, d'après l'édition 1913 du dictionnaire Webster, illustre très bien ceci : « une collection de boîtes, cases ou d'objets de ce type, d'une taille graduée, les unes dans les autres. »
[37] Les mots « argument » et « paramètre » sont souvent utilisés sans distinction. Dans le contexte de ce document, ils ont exactement la même signification, celle d'une variable passée à un script ou à une fonction.
[38] Dans un script, dans un sous-shell, $$ renvoie le PID du script, pas celui du sous-shell.