La plupart des scripts shell sont des solutions rapides et sales pour des problèmes non complexes. Du coup, les optimiser pour la rapidité n'est pas vraiment un problème. Considérez le cas où un script réalise une tâche importante, le fait bien mais tourne trop lentement. Le réécrire avec un langage compilé peut ne pas être une option trés agréable. La solution la plus simple serait de réécrire les parties du script qui le ralentissent. Est-il possible d'appliquer les principes de l'optimisation de code même à un script lent?
Vérifiez les boucles dans le script. Le temps consommé par des opérations répétitives s'ajoute rapidement. Si c'est possible, supprimez les opérations consomnatrices de temps des boucles.
Utilisez les commandes internes plutôt que les commandes système. Ces commandes intégrées s'exécutent plus rapidement et ne lancent habituellement pas un sous-shell lors de leur appel.
Eviter les commandes non nécessaires, particulièrement dans un tuyau.
cat "$fichier" | grep "$mot" grep "$mot" "$fichier" # Les lignes de commandes ci-dessus ont un effet identique, mais le deuxième #+ tourne plus vite comme il est lancé sur moins de processus. |
Utilisez les outils time et times pour vérifier les commandes particulièrement intensives. Considérez la réécriture des sections critiques en code C, voire en assembleur.
Essayez de minimiser les entrées/sorties fichier. Bash n'est pas particulièrement efficace sur la gestion des fichiers, donc considérez l'utilisation d'outils plus appropriés pour ceci dans le script, tels que awk ou Perl.
Ecrivez vos scripts d'une façon structurée, cohérente, ainsi ils peuvent être réorganisés et sécurisés selon les besoins. Quelques unes des techniques d'optimisation applicables aux langages de haut niveau peuvent fonctionner pour des scripts, mais d'autres, tels que le déroulement de boucles, sont pratiquement impossibles. Par dessus tout, utilisez votre bon sens.
Pour une excellente démonstration du fait qu'une optimisation drastique réduit le temps d'exécution d'un script, voir Exemple 12-32.
Précédent | Sommaire | Suivant |
<< Coloriser >> des scripts | Niveau supérieur | Astuces assorties |
exponentielle
# Bash, version 2.02, introduit l'opérateur exponentielle "**". let "z=5**3" echo "z = $z" # z = 125 |
modulo, ou mod (renvoie le reste de la division d'un entier)
bash$ echo `expr 5 % 3` 2 |
Cet opérateur trouve son utilité dans, entre autres choses, la génération de nombres compris dans une échelle donnée (voir Exemple 9-23 et Exemple 9-25) et pour le formattage de la sortie d'un programme (voir Exemple 26-8 et Exemple A-7). Il peut même être utiliser pour générer des nombres premiers (voir Exemple A-17). L'opérateur Modulo revient, de manière surprenante, assez souvent dans de nombreuses astuces numériques.
Exemple 8-1. Plus grand diviseur commun
#!/bin/bash # gcd.sh: plus grand diviseur commun # Utilise l'algorithme d'Euclide # Le "plus grand diviseur commun" (pgcd) de deux entiers est l'entier le plus #+ important qui divisera les deux sans reste. # L'algorihtme d'Euclide utilise des divisions successives. # A chaque passe, #+ dividende <--- diviseur #+ diviseur <--- reste #+ jusqu'à ce que reste 0. #+ pgcd = dividende, à la dernière passe. # # Pour une excellente discussion de l'algorithme d'Euclide, voir le site # de Jim Loy, http://www.jimloy.com/number/euclids.htm. # ------------------------------------------------------ # Vérification des arguments ARGS=2 E_MAUVAISARGS=65 if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` premier_nombre deuxieme-nombre" exit $E_MAUVAISARGS fi # ------------------------------------------------------ pgcd () { # Affectation arbitraire. dividende=$1 # Cela ne fait rien lequel est le diviseur=$2 #+ plus importante. # Pourquoi? reste=1 # Si une variable non initialisée est utilisée #+ dans la boucle, #+ cela finit en un message d'erreur lors de #+ la première passe dans la boucle. until [ "$reste" -eq 0 ] do let "reste = $dividende % $diviseur" dividende=$diviseur # Maintenant, répétez avec les deux plus #+ petits nombres. diviseur=$reste done # Algorithme d'Euclide } # Le dernier $dividende est le pgcd. pgcd $1 $2 echo; echo "PGCD de $1 et $2 = $dividende"; echo # Exercice : # -------- # Vérifier les arguments en ligne de commande pour s'assurer qu'ils sont des #+ entiers et quitter le script avec une erreur appropriée le cas contraire. exit 0 |
<< plus-égal >> (incrémente une variable par une constante)
let "var += 5" renvoie dans var sa propre valeur incrémentée de 5.
<< moins-égal >> (décrémente une variable par une constante)
<< multiplication-égal >> (multiplie une variable par une constante)
let "var *= 4" renvoie dans var sa propre valeur multipliée par 4.
<< division-égal >> (divise une variable par une constante)
<< modulo-égal >> (reste de la division de la variable avec une constante)
Les opérateurs arithmétiques sont trouvés souvent dans une expression expr ou let.
Exemple 8-2. Utiliser des opérations arithmétiques
#!/bin/bash # Compter jusqu'à 6 de 5 façons différentes. n=1; echo -n "$n " let "n = $n + 1" # let "n = n + 1" fonctionne aussi. echo -n "$n " : $((n = $n + 1)) # ":" nécessaire parce que sinon Bash essaie d'interpréter #+ "$((n = $n + 1))" comme une commande. echo -n "$n " n=$(($n + 1)) echo -n "$n " : $[ n = $n + 1 ] # ":" nécessaire parce que sinon Bash essaie d'interpréter #+ "$[ n = $n + 1 ]" comme une commande. # Fonctionne même si "n" a été initialisé comme une chaîne de caractères. echo -n "$n " n=$[ $n + 1 ] # Fonctionne même si "n" a été initialisé comme une chaîne de caractères. #* Eviter ce type de construction, car elle est obsolète et non portable. echo -n "$n "; echo # Merci, Stephane Chazelas. exit 0 |
![]() | Les variables de type entier dans Bash sont réellement de type entier long signé (32-bit), dans la plage -2147483648 à 2147483647. Une opération qui prend une variable en dehors de ces limites donnera un résultat erroné.
|
![]() | Bash ne comprend pas l'arithmérique à virgule flottante. Il traite les nombres contenant un point décimal comme des chaînes de caractères.
|
opérateurs de bits. Les opérateurs de bits font rarement une apparition dans les scripts shell. Leur utilisation principale semble d'être la manipulation et le test de valeurs lues à partir de ports ou de sockets. Le << renversement de bit >> est plus intéressant pour les langages compilés, comme le C et le C++, qui fonctionnent assez rapidement pour permettre une utilisation en temps réel.
décalage gauche d'un bit (revient à multiplier par 2 pour chaque décalage)
<< décalage gauche-égal >>
let "var <<= 2" renvoie dans var sa propre valeur décalée à gauche de 2 bits (donc multipliée par 4)
décalage droit d'un bit (revient à diviser par 2 pour chaque position du décalage)
<< décalage droit-égal >> (inverse de >>=)
et binaire
<< et-égal binaire >>
OU binaire
<< OU-égal binaire >>
négation binaire
NON binaire
XOR binaire
<< XOR-égal binaire >>
et (logique)
if [ $condition1 ] && [ $condition2 ] # Identique à: if [ $condition1 -a $condition2 ] # Renvoie vrai si à la fois condition1 et condition2 sont vraies... if [[ $condition1 && $condition2 ]] # Fonctionne aussi. # Notez que l'opérateur && n'est pas autorisé dans une construction [ ... ]. |
![]() | && peut aussi, suivant le contexte, être utilisé dans une liste and pour concaténer des commandes. |
ou (logique)
if [ $condition1 ] || [ $condition2 ] # Identique à: if [ $condition1 -o $condition2 ] # Renvoie vrai si soit condition1 soit condition2 est vraie... if [[ $condition1 || $condition2 ]] # Fonctionne aussi. # Notez que l'opérateur || n'est pas autorisé dans des constructions [ ... ]. |
![]() | Bash teste l'état de sortie de chaque instruction liée avec un opérateur logique. |
Exemple 8-3. Tests de condition composés en utilisant && et ||
#!/bin/bash a=24 b=47 if [ "$a" -eq 24 ] && [ "$b" -eq 47 ] then echo "Le test #1 a réussi." else echo "Le test #1 a échoué." fi # ERREUR: si [ "$a" -eq 24 && "$b" -eq 47 ] # essaie d'exécuter ' [ "$a" -eq 24 ' # et échoue à trouver le ']' correspondant. # # si [[ $a -eq 24 && $b -eq 24 ]] fonctionne # (Le "&&" a une signification différente en ligne 17 qu'en ligne 6.) # Merci, Stephane Chazelas. if [ "$a" -eq 98 ] || [ "$b" -eq 47 ] then echo "Le test #2 a réussi." else echo "Le test #2 a échoué." fi # Les options -a et -o apportent une alternative au test de la condition composée. # Merci à Patrick Callahan pour avoir remarqué ceci. if [ "$a" -eq 24 -a "$b" -eq 47 ] then echo "Le test #3 a réussi." else echo "Le test #3 a échoué." fi if [ "$a" -eq 98 -o "$b" -eq 47 ] then echo "Le test #4 a réussi." else echo "Le test #4 a échoué." fi a=rhino b=crocodile if [ "$a" = rhino ] && [ "$b" = crocodile ] then echo "Le test #5 a réussi." else echo "Le test #5 a échoué." fi exit 0 |
Les opérateurs && et || trouvent aussi leur utilité dans un contexte arithmétique.
bash$ echo $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0)) 1 0 1 0 |
opérateur virgule
L'opérateur virgule chaîne ensemble deux ou plusieurs opérations arithmétiques. Toutes les opérations sont évaluées (avec des possibles effets indésirables), mais seule la dernière opération est renvoyée.
let "t1 = ((5 + 3, 7 - 1, 15 - 4))" echo "t1 = $t1" # t1 = 11 let "t2 = ((a = 9, 15 / 3))" # Initialise "a" et calcule "t2". echo "t2 = $t2 a = $a" # t2 = 5 a = 9 |
L'opérateur virgule trouve son utilité principalement dans les boucles for. Voir Exemple 10-12.
Précédent | Sommaire | Suivant |
Opérations et thèmes relatifs | Niveau supérieur | Constantes numériques |
Exemple 10-17. Syntaxe à la C pour une boucle while
#!/bin/bash # wh-loopc.sh: Compter jusqu'à 10 dans une boucle "while". LIMITE=10 a=1 while [ "$a" -le $LIMITE ] do echo -n "$a " let "a+=1" done # Pas de surprises, jusqu'ici. echo; echo # +=================================================================+ # Maintenant, de nouveau mais avec une syntaxe C. ((a = 1)) # a=1 # Les double parenthèses permettent les espaces pour initialiser une variable, #+ comme en C. while (( a <= LIMITE )) # Double parenthèses, et pas de "$" devant la variable. do echo -n "$a " ((a += 1)) # let "a+=1" # Oui, en effet. # Les double parenthèses permettent d'incrémenter une varibale avec une #+ syntaxe style C. done echo # Maintenant, les programmeurs C se sentent chez eux avec Bash. exit 0 |
![]() | Une boucle while peut avoir son stdin redirigé vers un fichier par un < à la fin. |
Cette construction teste une condition au début de la boucle et continue à boucler tant que la condition est fausse (l'opposé de la boucle while).
until [condition-est-vraie]
do
commande...
done
Notez qu'une boucle until teste la condition de fin au début de la boucle, contrairement aux constructions similaires dans certains langages de programmation.
Comme c'est la cas avec les boucles for/in, placez do sur la même ligne que le test de la condition nécessite un point virgule.
until [condition-est-vraie] ; do
Précédent | Sommaire | Suivant |
Boucles et branchements | Niveau supérieur | Boucles imbriquées |
Le nombre de secondes pendant lequel le script s'exécutait.
#!/bin/bash LIMITE_TEMPS=10 INTERVALLE=1 echo echo "Tapez sur Control-C pour sortir avant $LIMITE_TEMPS secondes." echo while [ "$SECONDES" -le "$LIMITE_TEMPS" ] do if [ "$SECONDES" -eq 1 ] then unites=seconde else unites=secondes fi echo "Ce script tourne depuis $SECONDES $unites." # Sur une machine lente, le script peut laisser échapper un élément du #+ comptage quelque fois dans la boucle while. sleep $INTERVALLE done echo -e "\a" # Beep! exit 0 |
la liste des options activées du shell, une variable en lecture seule
bash$ echo $SHELLOPTS braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs |
Niveau du shell, comment Bash est imbriqué. Si, à la ligne de commande, $SHLVL vaut 1, alors, dans un script, il sera incrémenté et prendra la valeur 2.
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.
![]() | Malheureusement, ceci fonctionne seulement lors de l'attente d'une saisie sur une invite de la console ou dans un xterm. Bien qu'il serait sympathique de spéculer sur l'utilité de cette variable interne pour des saisies avec expiration de délai, par exemple en combinaison avec read, $TMOUT ne fonctionnera pas dans ce contexte et est virtuellement inutile pour l'écriture de scripts shell. (Une information semble indiquer qu'un read avec délai fontionne sur ksh.) |
Implémenter une saisie avec délai dans un script est certainement possible, mais nécessiterait un code complexe. Une méthode est de configurer une boucle avec délai pour signaler au script lorsque le délai se termine. Ceci nécessite aussi une routine de gestion du signal pour récupérer (voir Exemple 30-5) l'interruption générée par la boucle de délai (ouf!).
Exemple 9-2. Saisie avec délai
#!/bin/bash # timed-input.sh # TMOUT=3 inutile dans un script LIMITETEMPS=3 # Trois secondes dans cette instance, peut être configuré avec #+ une valeur différente. AfficheReponse() { if [ "$reponse" = TIMEOUT ] then echo $reponse else # ne pas mixer les deux interfaces. echo "Votre légume favori est le $reponse" kill $! # Kill n'est plus nécessaire pour la fonction TimerOn lancé en #+ tâche de fond. # $! est le PID du dernier job lancé en tâche de fond. fi } TimerOn() { sleep $LIMITETEMPS && kill -s 14 $$ & # Attend 3 secondes, puis envoie sigalarm au script. } VecteurInt14() { reponse="TIMEOUT" AfficheReponse exit 14 } trap VecteurInt14 14 # Interruption de temps (14) détournée pour notre but. echo "Quel est votre légume favori?" TimerOn read reponse AfficheReponse # C'est une implémentation détournée de l'entrée de temps, #+ néanmoins l'option "-t" de "read" simplifie cette tâche. # Voir "t-out.sh", ci-dessous. # Si vous avez besoin de quelque chose de réellement élégant... #+ pensez à écrire l'application en C ou C++, #+ en utilisant les fonctions de la bibliothèque appropriée, telles que #+ 'alarm' et 'setitimer'. exit 0 |
Une autre méthode est d'utiliser stty.
Exemple 9-3. Encore une fois, saisie avec délai
#!/bin/bash # timeout.sh # Ecrit par Stephane Chazelas, # et modifié par l'auteur de ce document. INTERVALLE=5 # timeout interval lecture_timedout() { timeout=$1 nomvariable=$2 ancienne_configuration_tty=`stty -g` stty -icanon min 0 time ${timeout}0 eval read $nomvariable # ou simplement read $nomvariable stty "$ancienne_configuration_tty" # Voir la page man de "stty". } echo; echo -n "Quel est votre nom? Vite!" lecture_timedout $INTERVALLE votre_nom # Ceci pourrait ne pas fonctionner sur tous les types de terminaux. # Le temps imparti dépend du terminal (il est souvent de 25,5 secondes). echo if [ ! -z "$votre_nom" ] # Si le nom est entré avant que le temps ne se soit #+ écoulé... then echo "Votre nom est $votre_nom." else echo "Temps écoulé." fi echo # Le comportement de ce script diffère un peu de "timed-input.sh". # A chaque appui sur une touche, le compteur est réinitialisé. exit 0 |
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, comme 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 sujet au changement à partir de la ligne de commande ou à l'intérieur d'un script, et est la contre partie de l'intégré id.
Exemple 9-5. Suis-je root?
#!/bin/bash # am-i-root.sh: Suis-je root ou non? ROOT_UID=0 # Root a l'identifiant $UID 0. if [ "$UID" -eq "$ROOT_UID" ] # Le vrai "root" peut-il se lever, s'il-vous-plaît? then echo "Vous êtes root." else echo "Vous êtes simplement un utilisateur ordinaire (mais maman vous aime tout autant.)." fi exit 0 # ============================================================= # # Le code ci-dessous ne s'exécutera pas, parce que le script s'est déjà arrêté. # Une autre méthode d'arriver à la même fin: NOM_UTILISATEURROOT=root nomutilisateur=`id -nu` # Ou... nomutilisateur=`whoami` if [ "$nomutilisateur" = "$NOM_UTILISATEURROOT" ] then echo "Vous êtes root." else echo "Vous êtes juste un gars régulier." fi |
Voir aussi Exemple 2-2.
![]() | Les variables $ENV, $LOGNAME, $MAIL, $TERM, $USER et $USERNAME ne sont pas des variables intégrés à Bash. Elles sont néanmois 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.
|
Paramètres de position
paramètres de positions, passés à partir de la ligne de commande à un script, passés à une fonction, ou initialisés (set) à une variable (voir Exemple 4-5 et Exemple 11-13)
nombre d'arguments sur la ligne de commande [2] ou de paramètres de position (voir Exemple 34-2)
Tous les paramètres de position, vus comme un seul mot
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é.
Exemple 9-6. arglist: Affichage des arguments avec $* et $@
#!/bin/bash # Appelez ce script avec plusieurs arguments, tels que "un deux trois". E_BADARGS=65 if [ ! -n "$1" ] then echo "Usage: `basename $0` argument1 argument2 etc." exit $E_BADARGS fi echo index=1 echo "Liste des arguments avec \"\$*\":" for arg in "$*" # Ne fonctionne pas correctement si "$*" n'est pas entre guillemets. do echo "Arg #$index = $arg" let "index+=1" done # $* voit tous les arguments comme un mot entier. echo "Liste entière des arguments vue comme un seul mot." echo index=1 echo "Liste des arguments avec \"\$@\":" for arg in "$@" do echo "Arg #$index = $arg" let "index+=1" done # $@ voit les arguments comme des mots séparés. echo "Liste des arguments vue comme des mots séparés." echo exit 0 |
Suite à un shift, $@ contient le reste des paramètres de la ligne de commande, sans le précédent $1, 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 Exemple 12-17 et Exemple 12-18.
![]() | Les paramètres $* et $@ affichent quelque fois un comportement inconsistent et bizarre, suivant la configuration de $IFS. |
Exemple 9-7. Comportement de $* et $@ inconsistent
#!/bin/bash # Comportement non prédictible des variables internes Bash "$*" et "$@", #+ suivant qu'elles soient ou non entre guillemets. # Gestion inconsistente de la séparation de mots et des retours chariot. set -- "Premier un" "second" "troisième:un" "" "Cinquième: :un" # Initialise les arguments du script, $1, $2, etc. echo echo 'IFS inchangée, utilisant "$*"' c=0 for i in "$*" # entre guillemets do echo "$((c+=1)): [$i]" # Cette ligne reste identique à chaque instance. # Arguments de echo. done echo --- echo 'IFS inchangée, utilisant $*' c=0 for i in $* # entre guillemets do echo "$((c+=1)): [$i]" done echo --- echo 'IFS inchangée, utilisant "$@"' c=0 for i in "$@" do echo "$((c+=1)): [$i]" done echo --- echo 'IFS inchangée, utilisant $@' c=0 for i in $@ do echo "$((c+=1)): [$i]" done echo --- IFS=: echo 'IFS=":", utilisant "$*"' c=0 for i in "$*" do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant $*' c=0 for i in $* do echo "$((c+=1)): [$i]" done echo --- var=$* echo 'IFS=":", utilisant "$var" (var=$*)' c=0 for i in "$var" do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant $var (var=$*)' c=0 for i in $var do echo "$((c+=1)): [$i]" done echo --- var="$*" echo 'IFS=":", utilisant $var (var="$*")' c=0 for i in $var do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant "$var" (var="$*")' c=0 for i in "$var" do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant "$@"' c=0 for i in "$@" do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant $@' c=0 for i in $@ do echo "$((c+=1)): [$i]" done echo --- var=$@ echo 'IFS=":", utilisant $var (var=$@)' c=0 for i in $var do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant "$var" (var=$@)' c=0 for i in "$var" do echo "$((c+=1)): [$i]" done echo --- var="$@" echo 'IFS=":", utilisant "$var" (var="$@")' c=0 for i in "$var" do echo "$((c+=1)): [$i]" done echo --- echo 'IFS=":", utilisant $var (var="$@")' c=0 for i in $var do echo "$((c+=1)): [$i]" done echo # Essayez ce script avec ksh ou zsh -y. exit 0 # Ce script exemple par Stephane Chazelas, # et légèrement modifié par l'auteur de ce document. |
![]() | Les paramètres $@ et $* diffèrent seulement lorsqu'ils sont entre des guillemets doubles. |
Exemple 9-8. $* et $@ lorsque $IFS est vide
#!/bin/bash # Si $IFS est initialisé, mais vide, # alors "$*" et "$@" n'affiche pas les paramètres de position comme on pourrait # s'y attendre. mecho () # Affiche les paramètres de position. { echo "$1,$2,$3"; } IFS="" # Initialisé, mais vide. set a b c # Paramètres de position. mecho "$*" # abc,, mecho $* # a,b,c mecho $@ # a,b,c mecho "$@" # a,b,c # Le comportement de $* et $@ quand $IFS est vide dépend de la version de # Bash ou sh. # Personne ne peux donc conseiller d'utiliser cette "fonctionnalité" dans un # script. # Merci, S.C. exit 0 |
Autres paramètres spéciaux
Les options passées au script (en utilisant set). Voir Exemple 11-13.
![]() | 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. |
PID (identifiant du processus) du dernier job ayant fonctionné en tâche de fond
Variable spéciale initialisée au dernier argument de la dernièr commande exécutée.
Code de sortie d'une commande, fonction, ou du script lui-même (voir Exemple 23-3)
Identifiant du processus du script lui-même. La variable $$ trouve fréquemment son utilité dans les scripts pour construire des noms de fichiers temporaires << uniques >> (voir Exemple A-14, Exemple 30-6, Exemple 12-23 et Exemple 11-23). Ceci est généralement plus simple que d'appeler mktemp.
[1] | Le pid du script en cours est $$, bien sûr. |
[2] | 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. |
Précédent | Sommaire | Suivant |
Les variables revisitées | Niveau supérieur | Manipuler les chaînes de caractères |
#!/bin/bash exec echo "Je sors \"$0\"." # Sortie du script ici. # ---------------------------------- # Les lignes suivantes ne s'exécutent jamais. echo "Cet echo ne sera jamais exécuté." exit 99 # Ce script ne sortira jamais par ici. # Vérifier le code de sortie après l'exécution du #+ du script avec un 'echo $?'. # Cela ne sera *pas* 99. |
Exemple 11-21. Un script lançant exec sur lui-même
#!/bin/bash # self-exec.sh echo echo "Cette ligne apparaît UNE FOIS dans le script, cependant elle continue à s'afficher." echo "Le PID de cette instance du script est toujours $$." # Démontre qu'un sous-shell n'est pas un processus fils. echo "==================== Tapez Ctl-C pour sortir ====================" sleep 1 exec $0 # Lance une autre instance du même script remplaçant le précédent. echo "Cette ligne ne s'affichera jamais!" # Pourquoi pas? exit 0 |
Un exec sert aussi à réaffecter les descripteurs de fichiers.exec <fichier-zzz remplace stdin par le fichier fichier-zzz (voir Exemple 16-1).
![]() | L'option -exec pour find n'est pas du tout la même chose que la commande shell intégrée exec. |
Cette commande permet de changer les options du shell au vol (voir Exemple 24-1 et Exemple 24-2). Elle apparait souvent dans les fichiers de démarrage de Bash, mais a aussi son utilité dans des scripts. Il est nécessaire de disposer de la version 2, ou ultérieurs, de Bash.
shopt -s cdspell # Permet des petites erreurs dans le nom des répertoires avec 'cd' cd /hpme # Oups! J'ai mal tapé '/home'. pwd # /home # Le shell a corrigé la faute de frappe. |
Une commande qui renvoie un succès (zéro) comme état de sortie, mais ne fait rien d'autre.
# Boucle sans fin while true # alias pour ":" do operation-1 operation-2 ... operation-n # A besoin d'un moyen pour sortir de la boucle. done |
Une commande qui renvoit un état de sortie correspondant à un échec, mais ne fait rien d'autre.
# Fausse boucle while false do # Le code suivant ne sera pas exécuté. operation-1 operation-2 ... operation-n # Rien ne se passe! done |
Identique à la commande externe which, type cmd donne le chemin complet vers << cmd >>. Contrairement à which, type est une commande intégrée à Bash. L'option -a est très utile pour que type identifie des mots clés et des commandes internes, et localise aussi les commandes système de nom identiques.
bash$ type '[' [ is a shell builtin bash$ type -a '[' [ is a shell builtin [ is /usr/bin/[ |
Enregistre le chemin des commandes spécifiées (dans une table de hachage du shell), donc le shell ou le script n'aura pas besoin de chercher le $PATH sur les appels futurs à ces commandes. Quand hash est appelé sans arguments, il liste simplement les commandes qui ont été hachées. L'option -r réinitialise la table de hachage.
help COMMANDE cherche un petit résumé sur l'utilisation de la commande COMMANDE intégrée au shell. C'est l'équivalent de whatis, pour les commandes intégrées.
bash$ help exit exit: exit [n] Exit the shell with a status of N. If N is omitted, the exit status is that of the last command executed. |
[1] | Une exception à ceci est la commande time, listée dans la documentation Bash officielle en tant que mot clé. |
[2] | Une option est un argument agissant comme un indicateur, changeant les comportements du script de façon binaire. L'argument associé avec une option particulière indique le comportement que l'option active ou désactive. |
Précédent | Sommaire | Suivant |
Tests et branchements | Niveau supérieur | Commandes de contrôle des jobs |