Vous êtes sur la page 1sur 107

Introduction la programmation en Bash

Version 0.1

Eric Sanchis

IUT de Rodez, 33 avenue du 8 mai 1945, 12000 Rodez Tl : 05.65.77.10.80 Fax : 05.65.77.10.81 Internet : www.iut-rodez.fr

Prface
Interprteur de commandes par dfaut des systmes GNU/Linux, bash est devenu pour les administrateurs systme, un outil incontournable. Ce document prsente les principales constructions syntaxiques de bash utilises dans lcriture des programmes shell (scripts shell). Lobjectif premier a t de laisser de ct les redondances syntaxiques de ce langage de programmation, la subtilit des mcanismes de linterprteur, afin dinsister sur quelques concepts synthtiques tels que la substitution, la redirection ou le filtrage. Cet crit tant destin principalement aux tudiants de premier et deuxime cycle en informatique, jai choisi de le rdiger en adoptant un style 2Ex (1 Explication, 1 Exemple) qui devrait permettre au lecteur de mieux sapproprier chaque notion prsente. Ce dernier pourra ensuite aborder des publications plus extensives ou plus spcialises. Cette publication tant loin dtre parfaite 1 , jencourage le lecteur me faire parvenir ses remarques ou suggestions, ainsi qu me signaler toute inexactitude (sanchis@iut-rodez.fr).

Pour en savoir plus :


[1] [2] [3] Mendel Cooper, Advanced Bash Scripting Guide (http://tldp.org/LDP/abs/html). Une traduction en franais est disponible (http://abs.traduc.org). Arnold Robbins, Nelson H. F. Beebe, Introduction aux scripts shell, Ed. OReilly, Paris, 2005. Cameron Newham, Bill Rosenblatt, Le shell bash, 3me dition, Ed. OReilly, Paris, 2006.

Plate-forme logicielle utilise :


Interprteur bash 3.1, systme PC/Debian

Licence :
GNU Free Documentation License

Les exemples figurant dans ce document ont pour but dillustrer les notions traites. Il nest donn aucune garantie quant leur fonctionnement ou leurs effets.

Table des matires


1. Introduction bash ---------------------------------------------------------------------------------------------------------- 5 1.1. 1.2. 1.3. 1.4. 1.5. 1.6. 2. Les shells --------------------------------------------------------------------------------------------------------------- 5 Syntaxe dune commande -------------------------------------------------------------------------------------------- 8 Commandes internes et externes ------------------------------------------------------------------------------------ 9 Modes dexcution dune commande ------------------------------------------------------------------------------ 11 Commentaires -------------------------------------------------------------------------------------------------------- 12 Fichiers shell --------------------------------------------------------------------------------------------------------- 13

Substitution de paramtres ------------------------------------------------------------------------------------------------ 15 2.1. 2.2. 2.3. 2.4. 2.5. Variables -------------------------------------------------------------------------------------------------------------- 15 Paramtres de position et paramtres spciaux------------------------------------------------------------------ 18 Suppression des ambiguts----------------------------------------------------------------------------------------- 24 Paramtres non dfinis ---------------------------------------------------------------------------------------------- 24 Suppression de variables-------------------------------------------------------------------------------------------- 26

3.

Substitution de commandes------------------------------------------------------------------------------------------------ 27 3.1. 3.2. Prsentation ---------------------------------------------------------------------------------------------------------- 27 Substitutions de commandes et paramtres rgionaux ---------------------------------------------------------- 29

4.

Caractres et expressions gnriques ------------------------------------------------------------------------------------ 31 4.1. 4.2. Caractres gnriques----------------------------------------------------------------------------------------------- 32 Expressions gnriques---------------------------------------------------------------------------------------------- 35

5.

Redirections lmentaires-------------------------------------------------------------------------------------------------- 37 5.1. 5.2. 5.3. Descripteurs de fichiers --------------------------------------------------------------------------------------------- 37 Redirections lmentaires------------------------------------------------------------------------------------------- 37 Tubes------------------------------------------------------------------------------------------------------------------- 42

6. 7.

Groupement de commandes ----------------------------------------------------------------------------------------------- 44 Code de retour --------------------------------------------------------------------------------------------------------------- 47 7.1. 7.2. 7.3. 7.4. 7.5. 7.6. Paramtre spcial ?------------------------------------------------------------------------------------------------- 47 Code de retour d'un programme shell ----------------------------------------------------------------------------- 50 Commande interne exit ---------------------------------------------------------------------------------------------- 50 Code de retour d'une suite de commandes------------------------------------------------------------------------ 51 Rsultats et code de retour------------------------------------------------------------------------------------------ 52 Oprateurs && et || sur les codes de retour------------------------------------------------------------------- 52

8.

Structures de contrle case et while-------------------------------------------------------------------------------------- 55 8.1. 8.2. Choix multiple case -------------------------------------------------------------------------------------------------- 55 Itration while -------------------------------------------------------------------------------------------------------- 56

9.

Chanes de caractres ------------------------------------------------------------------------------------------------------- 61

9.1. 9.2. 9.3. 9.4. 9.5. 10. 10.1. 10.2. 11. 11.1. 11.2. 11.3. 11.4. 11.5. 11.6. 12. 12.1. 12.2. 12.3. 12.4. 13. 13.1. 13.2. 14. 14.1. 14.2. 14.3. 14.4. 14.5. 14.6. 14.7. 14.8. 14.9. 14.10.

Protection de caractres -------------------------------------------------------------------------------------------- 61 Longueur d'une chane de caractres ----------------------------------------------------------------------------- 62 Modificateurs de chanes-------------------------------------------------------------------------------------------- 62 Extraction de sous-chanes ----------------------------------------------------------------------------------------- 64 Remplacement de sous-chanes------------------------------------------------------------------------------------- 65 Structures de contrle for et if----------------------------------------------------------------------------------------- 67 Itration for ---------------------------------------------------------------------------------------------------------- 67 Choix if --------------------------------------------------------------------------------------------------------------- 69 Entiers et expressions arithmtiques --------------------------------------------------------------------------------- 75 Variables de type entier --------------------------------------------------------------------------------------------- 75 Commande interne ((------------------------------------------------------------------------------------------------ 75 Valeur d'une expression arithmtique ----------------------------------------------------------------------------- 77 Oprateurs ------------------------------------------------------------------------------------------------------------ 78 Structure for pour les expressions arithmtiques ---------------------------------------------------------------- 83 Exemple : les tours de Hanoi --------------------------------------------------------------------------------------- 84 Tableaux ------------------------------------------------------------------------------------------------------------------- 86 Dfinition et initialisation dun tableau --------------------------------------------------------------------------- 86 Valeur d'un lment d'un tableau ---------------------------------------------------------------------------------- 87 Caractristiques d'un tableau -------------------------------------------------------------------------------------- 88 Suppression d'un tableau-------------------------------------------------------------------------------------------- 89 Alias------------------------------------------------------------------------------------------------------------------------- 90 Cration dun alias -------------------------------------------------------------------------------------------------- 90 Suppression dun alias ---------------------------------------------------------------------------------------------- 92 Fonctions shell ------------------------------------------------------------------------------------------------------------ 93 Dfinition dune fonction-------------------------------------------------------------------------------------------- 93 Suppression dune fonction ----------------------------------------------------------------------------------------- 96 Trace des appels aux fonctions ------------------------------------------------------------------------------------- 96 Arguments dune fonction------------------------------------------------------------------------------------------- 97 Variables locales une fonction ----------------------------------------------------------------------------------- 99 Exporter une fonction---------------------------------------------------------------------------------------------- 101 Commande interne return----------------------------------------------------------------------------------------- 103 Substitution de fonction ------------------------------------------------------------------------------------------- 104 Fonctions rcursives ----------------------------------------------------------------------------------------------- 104 Appels de fonctions disperses dans plusieurs fichiers-------------------------------------------------------- 105

1. Introduction bash
1.1. Les shells
Sous Unix, on appelle shell linterprteur de commandes qui fait office d'interface entre l'utilisateur et le systme dexploitation. Les shells sont des interprteurs : cela signifie que chaque commande saisie par lutilisateur (ou lue partir dun fichier) est syntaxiquement vrifie puis excute. Il existe de nombreux shells qui se classent en deux grandes familles : - la famille C shell (ex : csh, tcsh) - la famille Bourne shell (ex : sh, bash, ksh). zsh est un shell qui contient les caractristiques des deux familles prcdentes. Nanmoins, le choix dutiliser un shell plutt quun autre est essentiellement une affaire de prfrence personnelle ou de circonstance. En connatre un, permet daccder aisment aux autres. Lorsque lon utilise le systme GNU/Linux (un des nombreux systmes de la galaxie Unix), le shell par dfaut est bash (Bourne Again SHell). Ce dernier a t conu en 1988 par Brian Fox dans le cadre du projet GNU 2 . Aujourdhui, les dveloppements de bash sont mens par Chet Ramey. Un shell possde un double aspect : - un aspect environnement de travail - un aspect langage de programmation. 1.1.1. Un environnement de travail En premier lieu, un shell doit fournir un environnement de travail agrable et puissant. Par exemple, bash permet (entre autres) : - le rappel des commandes prcdentes (gestion de lhistorique) ; cela vite de taper plusieurs fois la mme commande - la modification en ligne du texte de la commande courante (ajout, retrait, remplacement de caractres) en utilisant les commandes ddition de lditeur de texte vi ou emacs - la gestion des travaux lancs en arrire-plan (appels jobs) ; ceux-ci peuvent tre dmarrs, stopps ou repris suivant les besoins - linitialisation adquate de variables de configuration (chane dappel de linterprteur, chemins de recherche par dfaut) ou la cration de raccourcis de commandes (commande alias). Illustrons cet ajustement de configuration par un exemple. Le shell permet dexcuter une commande en mode interactif ou bien par l'intermdiaire de fichiers de commandes (scripts). En mode interactif, bash affiche lcran une chane dappel (appele galement prompt ou invite), qui se termine par dfaut par le caractre # suivi dun caractre espace pour ladministrateur systme (utilisateur root) et par le caractre $ suivi dun caractre espace pour les autres utilisateurs. Cette chane dappel peut tre relativement longue. Ex :
sanchis@jade:/bin$

http://www.gnu.org

Celle-ci est constitue du nom de connexion de lutilisateur (sanchis), du nom de la machine sur laquelle lutilisateur travaille (jade) et du chemin absolu du rpertoire courant de lutilisateur (/bin). Elle indique que le shell attend que lutilisateur saisisse une commande et la valide en appuyant sur la touche entre. Bash excute alors la commande puis raffiche la chane dappel. Si lon souhaite raccourcir cette chane dappel, il suffit de modifier la valeur de la variable prdfinie du shell PS1 (Prompt Shell 1). Ex :
sanchis@jade:/bin$ PS1='$ ' $ pwd /home/sanchis => pwd affiche le chemin absolu du rpertoire courant $

La nouvelle chane dappel est constitue par le caractre $ suivi dun caractre espace. 1.1.2. Un langage de programmation Les shells ne sont pas seulement des interprteurs de commandes mais galement de vritables langages de programmation. Un shell comme bash intgre : - les notions de variable, doprateur arithmtique, de structure de contrle, de fonction, prsentes dans tout langage de programmation classique, mais aussi - des oprateurs spcifiques (ex : |, ;) Ex :
$ a=5 $ $ echo $((a +3 )) 8 $

=> affectation de la valeur 5 la variable a => affiche la valeur de lexpression a+3

Loprateur |, appel tube, est un oprateur caractristique des shells et connecte la sortie dune commande lentre de la commande suivante. Ex :
$ ruptime iutbis up jade up mobile1 up mobile2 up quartz up sigma up $ $ ruptime | wc -l 6 $ 56+22:50, 39+16:17, 3+02:19, 2+18:43, 40+15:35, 56+23:46, 0 2 0 0 2 1 users, users, users, users, users, user, load load load load load load 0.47, 0.00, 0.00, 0.00, 0.00, 0.00, 0.48, 0.00, 0.00, 0.00, 0.00, 0.00, 0.34 0.00 0.00 0.00 0.00 0.00

La commande unix ruptime 3 affiche les noms et autres informations relatives aux machines visibles sur le rseau. La commande unix wc munie de loption l affiche le nombre de lignes quelle a t en mesure de lire. En connectant avec un tube la sortie de ruptime lentre de la commande wc l, on obtient le nombre de machines visibles du rseau. Mme si au fil du temps de nouveaux types de donnes comme les entiers ou les tableaux ont t introduits dans certains shells, ces derniers manipulent essentiellement des chanes de caractres :
3

La commande ruptime est contenue dans le paquetage rwho. Ce paquetage nest pas systmatiquement install par les distributions Linux.

ce sont des langages de programmation orients chanes de caractres. Cest ce qui rend les shells la fois si puissants et si dlicats utiliser. Lobjet de ce document est de prsenter de manire progressive les caractristiques de bash comme langage de programmation. 1.1.3. Atouts et inconvnients des shells Ltude dun shell tel que bash en tant que langage de programmation possde plusieurs avantages : - cest un langage interprt : les erreurs peuvent tre facilement localises et traites ; dautre part, des modifications de fonctionnalits sont facilement apportes lapplication sans quil soit ncessaire de recompiler et faire ldition de liens de lensemble - le shell manipule essentiellement des chanes de caractres: on ne peut donc construire des structures de donnes complexes laide de pointeurs, ces derniers nexistant pas en shell. Ceci a pour avantage dviter des erreurs de typage et de pointeurs mal grs. Le dveloppeur raisonne de manire uniforme en termes de chanes de caractres - le langage est adapt au prototypage rapide dapplications : les tubes, les substitutions de commandes et de variables favorisent la construction dune application par assemblage de commandes prexistantes dans lenvironnement Unix - cest un langage glu : il permet de connecter des composants crits dans des langages diffrents. Ces derniers doivent uniquement respecter quelques rgles particulirement simples. Le composant doit tre capable : de lire sur lentre standard, daccepter des arguments et options ventuels, dcrire ses rsultats sur la sortie standard, dcrire les messages derreur sur la sortie standard ddie aux messages derreur. Cependant, bash et les autres shells en gnral ne possdent pas que des avantages : - issus dUnix, systme dexploitation crit lorigine par des dveloppeurs pour des dveloppeurs, les shells utilisent une syntaxe sotrique daccs difficile pour le dbutant - loubli ou lajout dun caractre espace provoque facilement une erreur de syntaxe - bash possde plusieurs syntaxes pour implanter la mme fonctionnalit, comme la substitution de commande ou lcriture dune chane lcran. Cela est principalement d la volont de fournir une compatibilit ascendante avec le Bourne shell, shell historique des systmes Unix - certains caractres spciaux, comme les parenthses, ont des significations diffrentes suivant le contexte ; en effet, les parenthses peuvent introduire une liste de commandes, une dfinition de fonction ou bien imposer un ordre dvaluation dune expression arithmtique. Toutefois, afin de rendre ltude de bash plus aise, nous naborderons pas sa syntaxe de manire exhaustive ; en particulier, lorsquil existera plusieurs syntaxes pour mettre en oeuvre la mme fonctionnalit, une seule dentre elles sera prsente. 1.1.4. Shell utilis La manire la plus simple de connatre le shell que lon utilise est dexcuter la commande unix ps qui liste les processus de lutilisateur : Ex :
$ ps

PID TTY 6908 pts/4 6918 pts/4 $

TIME CMD 00:00:00 bash 00:00:00 ps

=> linterprteur utilis est bash

Comme il existe plusieurs versions de bash prsentant des caractristiques diffrentes, il est important de connatre la version utilise. Pour cela, on utilise l'option -version de bash. Ex :
$ bash --version GNU bash, version 3.1.14(1)-release (i486-pc-linux-gnu) Copyright (C) 2005 Free Software Foundation, Inc. $

La dernire version majeure de bash est la version 3. Cest celle qui sera tudie.

1.2. Syntaxe dune commande


La syntaxe gnrale d'une commande (unix ou de bash) est la suivante : [ chemin/]nom_cmd [ option ... ] [ argument ... ] C'est une suite de mots spars par un ou plusieurs blancs. On appelle blanc un caractre tab (tabulation horizontale) ou un caractre espace. Un mot est une suite de caractres non blancs. Cependant, plusieurs caractres ont une signification spciale pour le shell et provoquent la fin d'un mot : ils sont appels mta-caractres (ex : |, <). Bash utilise galement des oprateurs de contrle (ex : (, ||) et des mots rservs pour son propre fonctionnement : ! fi time case fo until do function while done if { elif in } else select [[ esac then ]]

Bash distingue les caractres majuscules des caractres minuscules. Le nom de la commande est le plus souvent le premier mot. Une option est gnralement introduite par le caractre tiret (ex : -a) ou dans la syntaxe GNU par deux caractres tiret conscutifs (ex : --version). Elle prcise un fonctionnement particulier de la commande. La syntaxe [ elt ... ] signifie que llment elt est facultatif (introduit par la syntaxe [elt ]) ou bien prsent une ou plusieurs fois (syntaxe elt ). Cette syntaxe ne fait pas partie du shell ; elle est uniquement descriptive (mta-syntaxe). Les arguments dsignent les objets sur lesquels doit sexcuter la commande. Ex : ls -l RepC RepD : commande ls avec loption l et les arguments RepC et RepD

Lorsque lon souhaite connatre la syntaxe ou les fonctionnalits dune commande cmd (ex : ls ou bash) il suffit dexcuter la commande man cmd (ex : man bash). Laide en ligne de la commande cmd devient alors disponible. 8

1.3. Commandes internes et externes


Le shell distingue deux sortes de commandes : - les commandes internes - les commandes externes. 1.3.1. Commandes internes Une commande interne est une commande dont le code est implant au sein de linterprteur de commande. Cela signifie que, lorsquon change de shell courant ou de connexion, par exemple en passant de bash au C-shell, on ne dispose plus des mmes commandes internes. Exemples de commandes internes : cd , echo , for , pwd Sauf dans quelques cas particuliers, linterprteur ne cre pas de processus pour excuter une commande interne. Les commandes internes de bash peuvent se dcomposer en deux groupes : - les commandes simples (ex : cd, echo) - les commandes composes (ex : for, ((, {). Commandes simples

Parmi lensemble des commandes internes, echo est lune des plus utilise : echo : Cette commande interne affiche ses arguments sur la sortie standard en les sparant par un espace et va la ligne. Ex :
$ echo bonjour tout le bonjour tout le monde $ monde

Dans cet exemple, echo est invoque avec quatre arguments : bonjour, tout, le et monde. On remarquera que les espacements entre les arguments ne sont pas conservs lors de laffichage : un seul caractre espace spare les mots affichs. En effet, le shell prtraite la commande, liminant les blancs superflus. Pour conserver les espacements, il suffit dentourer la chane de caractres par une paire de guillemets : Ex :
$ echo bonjour tout le bonjour tout le $ monde monde

On dit que les blancs ont t protgs de l'interprtation du shell.

Pour afficher les arguments sans retour la ligne, on utilise loption -n de echo. Ex :
$ echo -n bonjour bonjour$

La chane dappel $ est crite sur la mme ligne que largument bonjour. Commandes composes

Les commandes composes de bash sont : case ... esac until ... done { ... } if ... fi while ... done (( )) for ... done [[ ... ]] select ... done ( ... )

Seuls le premier et le dernier mot de la commande compose sont indiqus. Les commandes composes sont principalement des structures de contrle. 1.3.2. Commandes externes Une commande externe est une commande dont le code se trouve dans un fichier ordinaire. Le shell cre un processus pour excuter une commande externe. Parmi lensemble des commandes externes que lon peut trouver dans un systme, nous utiliserons principalement les commandes unix (ex : ls, mkdir, vi, sleep) et les fichiers shell. La localisation du code d'une commande externe doit tre connue du shell pour qu'il puisse excuter cette commande. A cette fin, bash utilise la valeur de sa variable prdfinie PATH. Celle-ci contient une liste de chemins spars par le caractre : (ex : /bin:/usr/bin). Par exemple, lorsque lutilisateur lance la commande unix cal, le shell est en mesure de lexcuter et dafficher le calendrier du mois courant car le code de cal est situ dans le rpertoire /usr/bin prsent dans PATH. Ex :
$ cal septembre 2006 di lu ma me je ve 1 3 4 5 6 7 8 10 11 12 13 14 15 17 18 19 20 21 22 24 25 26 27 28 29 $

sa 2 9 16 23 30

Remarque : Ex :

pour connatre le statut dune commande, on utilise la commande interne type.

$ type sleep sleep is /bin/sleep => sleep est une commande externe $ type echo echo is a shell builtin $

10

1.4. Modes dexcution dune commande


Deux modes dexcution peuvent tre distingus : - lexcution squentielle - lexcution en arrire-plan. 1.4.1. Excution squentielle Le mode dexcution par dfaut dune commande est lexcution squentielle : le shell lit la commande entre par lutilisateur, lanalyse, la prtraite et si elle est syntaxiquement correcte, lexcute. Une fois lexcution termine, le shell effectue le mme travail avec la commande suivante. Lutilisateur doit donc attendre la fin de lexcution de la commande prcdente pour que la commande suivante puisse tre excute : on dit que lexcution est synchrone. Si on tape la suite de commandes : sleep 3 entre date entre o entre dsigne la touche entre, lexcution de date dbute aprs que le dlai de 3 secondes se soit coul. Pour lancer lexcution squentielle de plusieurs commandes sur la mme ligne de commande, il suffit de les sparer par un caractre ; Ex :
$ cd /tmp ; pwd; echo bonjour; cd ; pwd /tmp => affiche par lexcution de pwd bonjour => affiche par lexcution de echo bonjour /home/sanchis => affiche par lexcution de pwd $

Pour terminer lexcution dune commande lance en mode synchrone, on appuie simultanment sur les touches CTRL et C (notes control-C ou ^C). En fait, la combinaison de touches approprie pour arrter lexcution dune commande en mode synchrone est indique par la valeur du champ intr lorsque la commande unix stty est lance : Ex :
$ stty -a speed 38400 baud; rows 24; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; . . . $

Supposons que la commande cat soit lance sans argument, son excution semblera fige un utilisateur qui dbute dans lapprentissage dun systme Unix. Il pourra utiliser la combinaison de touches mentionne prcdemment pour terminer lexcution de cette commande. Ex :
$ cat ^C $

11

1.4.2. Excution en arrire-plan Lexcution en arrire-plan permet un utilisateur de lancer une commande et de rcuprer immdiatement la main pour lancer en parallle la commande suivante (paralllisme logique). On utilise le caractre & pour lancer une commande en arrire-plan. Dans lexemple ci-dessous, la commande sleep 5 (suspendre lexcution pendant 5 secondes) est lance en arrire-plan. Le systme a affect le numro didentification 696 au processus correspondant tandis que bash a affect un numro de travail (ou numro de job) gal 1 et affich [1]. Lutilisateur peut, en parallle, excuter dautres commandes (dans cet exemple, il sagit de la commande ps). Lorsque la commande en arrire-plan se termine, le shell le signale l'utilisateur aprs que ce dernier ait appuy sur la touche entre. Ex :
$ sleep 5 & [1] 696 $ ps PID TTY TIME CMD 683 pts/0 00:00:00 bash 696 pts/0 00:00:00 sleep 697 pts/0 00:00:00 ps => lutilisateur a appuy sur la touche entre mais sleep ntait pas termine $ $ => lutilisateur a appuy sur la touche entre et sleep tait termine [1]+ Done sleep 5 $

Ainsi, outre la gestion des processus spcifique Unix, bash introduit un niveau supplmentaire de contrle de processus. En effet, bash permet de stopper, reprendre, mettre en arrire-plan un processus, ce qui ncessite une identification supplmentaire (numro de job). Lexcution en arrire-plan est souvent utilise lorsquune commande est gourmande en temps CPU (ex : longue compilation dun programme).

1.5. Commentaires
Un commentaire dbute avec le caractre # et se termine avec la fin de la ligne. Un commentaire est ignor par le shell. Ex :
$ echo bonjour # lami bonjour $ echo coucou #l ami coucou $ # echo coucou $

Pour que le caractre # soit reconnu en tant que dbut de commentaire, il ne doit pas tre insr lintrieur dun mot ou terminer un mot. Ex :
$ echo il est#10 il est#10 heures $ $ echo bon# jour bon# jour $ heures

12

1.6. Fichiers shell


Lorsquun traitement ncessite lexcution de plusieurs commandes, il est prfrable de les sauvegarder dans un fichier plutt que de les retaper au clavier chaque fois que le traitement doit tre lanc. Ce type de fichier est appel fichier de commandes ou fichier shell ou encore script shell. Exercice 1 : 1.) A laide dun diteur de texte, crer un fichier premier contenant les lignes suivantes :
#!/bin/bash # premier echo -n "La date du jour est: " date

La notation #! en premire ligne d'un fichier interprt prcise au shell courant quel interprteur doit tre utilis pour excuter le script shell (dans cet exemple, il sagit de /bin/bash). La deuxime ligne est un commentaire. 2.) Ex : Vrifier le contenu de ce fichier.
$ cat premier #!/bin/bash # premier echo -n "La date du jour est: " date $

3.) Ex :

Pour lancer lexcution dun fichier shell fich, on peut utiliser la commande : bash fich
$ bash premier la date du jour est : dimanche 3 septembre 2006, 15:41:26 (UTC+0200) $

4.)

Il est plus simple de lancer lexcution dun programme shell en tapant directement son nom, comme on le ferait pour une commande unix ou une commande interne. Pour que cela soit ralisable, deux conditions doivent tre remplies : - lutilisateur doit possder les permissions r (lecture) et x (excution) sur le fichier shell - le rpertoire dans lequel se trouve le fichier shell doit tre prsent dans la liste des chemins contenue dans PATH.
$ ls -l premier -rw-r--r-- 1 sanchis sanchis 63 sep $ 3 15:39 premier

Ex :

Seule la permission r est possde par lutilisateur. 13

Pour ajouter la permission x au propritaire du fichier fich, on utilise la commande : chmod u+x fich Ex :

$ chmod u+x premier $ $ ls -l premier -rwxr--r-- 1 sanchis sanchis 63 sep $

3 15:39 premier

Si on excute premier en ltat, une erreur dexcution se produit. Ex :


$ premier -bash: premier: command not found $

=> Problme !

Cette erreur se produit car bash ne sait pas o se trouve le fichier premier. Ex :
$ echo $PATH /bin:/usr/bin:/usr/bin/X11 $ $ pwd /home/sanchis $

=> affiche la valeur de la variable PATH

Le rpertoire dans lequel se trouve le fichier premier (rpertoire /home/sanchis) nest pas prsent dans la liste de PATH. Pour que le shell puisse trouver le fichier premier, il suffit de mentionner le chemin permettant daccder celui-ci. Ex :
$ ./premier la date du jour est : dimanche 3 septembre 2006, 15:45:28 (UTC+0200) $

Pour viter davoir saisir systmatiquement ce chemin, il suffit de modifier la valeur de PATH en y incluant, dans notre cas, le rpertoire courant (.). Ex :
$ PATH=$PATH:. => ajout du rpertoire courant dans PATH $ $ echo $PATH /bin:/usr/bin:/usr/bin/X11:. $ $ premier la date du jour est : dimanche 3 septembre 2006, 15:47:38 (UTC+0200) $

Exercice 2 : Ecrire un programme shell repcour qui affiche le nom de connexion de l'utilisateur et le chemin absolu de son rpertoire courant de la manire suivante : Ex :
$ repcour mon nom de connexion est : sanchis mon repertoire courant est : /home/sanchis $

14

2. Substitution de paramtres
Dans la terminologie du shell, un paramtre dsigne toute entit pouvant contenir une valeur. Le shell distingue trois classes de paramtres : les variables, identifies par un nom Ex : a , PATH les paramtres de position, identifis par un numro Ex : 0 , 1 , 12 les paramtres spciaux, identifis par un caractre spcial Ex : # , ? , $ Le mode daffectation d'une valeur est spcifique chaque classe de paramtres. Suivant celle-ci, laffectation sera effectue par lutilisateur, par bash ou bien par le systme. Par contre, pour obtenir la valeur d'un paramtre, on placera toujours le caractre $ devant sa rfrence, et cela quelle que soit sa classe. Ex :
$ echo $PATH => affiche la valeur de la variable PATH /usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:.:/home/sanchis/bin $ echo $$ => affiche la valeur du paramtre spcial $ 17286 $

2.1. Variables
Une variable est identifie par un nom, c'est--dire une suite de lettres, de chiffres ou de caractres espace soulign ne commenant pas par un chiffre. Les lettres majuscules et minuscules sont diffrencies. Les variables peuvent tre classes en trois groupes : - les variables utilisateur (ex : a, valeur) - les variables prdfinies du shell (ex : PS1, PATH, REPLY, IFS) - les variables prdfinies de commandes unix (ex : TERM). En gnral, les noms des variables utilisateur sont en lettres minuscules tandis que les noms des variables prdfinies (du shell ou de commandes unix) sont en majuscules. Lutilisateur peut affecter une valeur une variable en utilisant - loprateur daffectation = - la commande interne read. Syntaxe : Affectation directe nom=[valeur] [ nom=[valeur] ... ]

Il est impratif que le nom de la variable, le symbole = et la valeur affecter ne forment quune seule chane de caractres.

15

Plusieurs affectations peuvent tre prsentes dans la mme ligne de commande. Ex :


$ x=coucou $ y=bonjour

=> la variable x contient la chane de caractres coucou => la variable y contient la chane bonjour

ATTENTION : les syntaxes daffectation errones les plus frquentes contiennent un ou plusieurs caractres espace entre le nom de la variable et le symbole =. Ex : $ b =coucou -bash: b: command not found $

Le shell interprte b comme une commande excuter ; ne la trouvant pas, il signale une erreur. un ou plusieurs caractres espace entre le symbole = et la valeur de la variable. Ex : $ y= coucou -bash: coucou: command not found $

La chane coucou est interprte comme la commande excuter.

Lorsque le shell rencontre la chane $x, il la remplace textuellement par la valeur de la variable x, c.--d. coucou ; la commande excute par bash est : echo x est coucou Ex :
$ echo x est $x x est coucou $

Il est important de remarquer que le nom dun paramtre et la valeur de ce paramtre ne se dsignent pas de la mme manire. Ex :
$ x=$x$y $ echo $x coucoubonjour $

=> x : contenant, $x : contenu

Affectation par lecture

Elle seffectue l'aide de la commande interne read. Celle-ci lit une ligne entire sur lentre standard. Syntaxe : Ex : read [ var1 ... ] => chanes saisies par lutilisateur et enregistres => respectivement dans les variables a et b

$ read a b bonjour Monsieur $ $ echo $b Monsieur $

16

Lorsque la commande interne read est utilise sans argument, la ligne lue est enregistre dans la variable prdfinie du shell REPLY . Ex :
$ read bonjour tout le monde $ $ echo $REPLY bonjour tout le monde $

Loption p de read affiche une chane dappel avant deffectuer la lecture ; la syntaxe utiliser est : read p chane_d_appel [ var ] Ex :
$ read -p "Entrez votre prenom : " prenom Entrez votre prenom : Eric $ $ echo $prenom Eric $

Remarques sur la commande interne read - Sil y a moins de variables que de mots dans la ligne lue, le shell affecte le premier mot la premire variable, le deuxime mot la deuxime variable, etc., la dernire variable reoit tous les mots restants. Ex :
$ read a b c un bon jour coucou $ $ echo $a un $ echo $c jour coucou $

- Sil y a davantage de variables que de mots dans la ligne lue, chaque variable reoit un mot et aprs puisement de ces derniers, les variables excdentaires sont vides (c.--d. initialises la valeur null). Ex :
$ read a b Un $ $ echo $a Un $ $ echo $b

=> valeur null


$

Exercice 1 : Ecrire un programme shell deuxfois qui affiche le message "Entrez un mot : ", lit le mot saisi par l'utilisateur puis affiche ce mot deux fois sur la mme ligne. Ex :
$ deuxfois Entrez un mot : toto toto toto $

17

Exercice 2 : Ecrire un programme shell untrois qui demande l'utilisateur de saisir une suite de mots constitue d'au moins trois mots et qui affiche sur la mme ligne le premier et le troisime mot saisis. Ex :
$ untrois Entrez une suite de mots : un petit coucou de Rodez un coucou $

Variable en lecture seule

Pour dfinir une variable dont la valeur ne doit pas tre modifie (appele constante dans dautres langages de programmation), on utilise la syntaxe : declare r nom=valeur [ nom=valeur ] Ex :
$ declare -r mess=bonjour $

On dit que la variable mess possde lattribut r. Une tentative de modification de la valeur dune constante provoque une erreur. Ex :
$ mess=salut -bash: mess: readonly variable $

Pour connatre la liste des constantes dfinies : Ex :

declare r

$ declare -r declare -ar BASH_VERSINFO='([0]="3" [1]="1" [2]="17" [3]="1" [4]="release" [5]="i486-pc-linux-gnu")' declare -ir EUID="1002" declare -ir PPID="25165" declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history: interactive-comments:monitor" declare -ir UID="1002" declare -r mess="bonjour" $

Plusieurs constantes sont prdfinies : le tableau BASH_VERSINFO (attribut a), les entiers EUID, PPID et UID (attribut i) et la chane SHELLOPTS.

2.2. Paramtres de position et paramtres spciaux


2.2.1. Paramtres de position Un paramtre de position est rfrenc par un ou plusieurs chiffres : 8 , 0 , 23 Lassignation de valeurs des paramtres de position seffectue : - soit laide de la commande interne set - soit lors de lappel dun fichier shell ou dune fonction shell. 18

ATTENTION : on ne peut utiliser ni le symbole =, ni la commande interne read pour affecter directement une valeur un paramtre de position. Ex : $ 23=bonjour -bash: 23=bonjour: command not found $ $ read 4 aa -bash: read: `4': not a valid identifier $

Commande interne set : La commande interne set affecte une valeur un ou plusieurs paramtres de position en numrotant ses arguments suivant leur position. La numrotation commence 1. Syntaxe : Ex : set arg1 ...

$ set alpha beta gamma => alpha est la valeur du paramtre de position 1, beta la $ => valeur du deuxime paramtre de position et gamma $ => la valeur du paramtre de position 3

Pour obtenir la valeur dun paramtre de position, il suffit de placer le caractre $ devant son numro ; ainsi, $1 permet dobtenir la valeur du premier paramtre de position, $2 la valeur du deuxime et ainsi de suite. Ex :
$ set ab be ga $ $ echo $3 $2 ga be $ $ echo $4 $

=> numrotation des mots ab, be et ga

Tous les paramtres de position sont rinitialiss ds que la commande interne set est utilise avec au moins un argument. Ex :
$ set coucou $ echo $1 coucou $ echo $2

=> les valeurs be et ga prcdentes ont disparues


$

La commande set -- rend indfinie la valeur des paramtres de position pralablement initialiss. Ex : $ set alpha beta
$ echo $1 alpha $ $ set -$ echo $1 $

=> les valeurs alpha et beta sont perdues

19

Remarques : - Utilise sans argument, set a un comportement diffrent : elle affiche la (longue) liste des noms et valeurs des variables dfinies. Ex :
$ set BASH=/bin/bash . . . $

- Si la valeur du premier argument de set commence par un caractre - ou +, une erreur se produit. En effet, les options de cette commande interne commencent par un de ces deux caractres. Pour viter que ce type derreur ne se produise, on utilise la syntaxe : set -- arg ... Ex :
$ a=+qui $ set $a -bash: set: +q: invalid option set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] $ set -- $a $ $ echo $1 +qui $

2.2.2. Paramtres spciaux Un paramtre spcial est rfrenc par un caractre spcial. Laffectation dune valeur un paramtre spcial est effectue par le shell. Pour obtenir la valeur dun paramtre spcial, il suffit de placer le caractre $ devant le caractre spcial qui le reprsente. Un paramtre spcial trs utilis est le paramtre # ( ne pas confondre avec le dbut dun commentaire). Celui-ci contient le nombre de paramtres de position ayant une valeur. Ex :
$ set a b c $ $ echo $# => affichage de la valeur du paramtre spcial # 3 => il y a 3 paramtres de position ayant une valeur $

Exercice 3 : Ecrire un programme shell nbmots qui demande l'utilisateur de saisir une suite quelconque de mots puis affiche le nombre de mots saisis. Ex :
$ nbmots Entrez une suite de mots : un deux trois quatre cinq 5 => 5 mots ont t saisis $

20

2.2.3. Commande interne shift La commande interne shift dcale la numrotation des paramtres de position ayant une valeur. Syntaxe : shift [ n ]

Elle renomme le n+1 ime paramtre de position en paramtre de position 1, le n+2 ime paramtre de position en paramtre de position 2, etc. : (n+1) => 1 , (n+2) => 2 , etc. Une fois le dcalage effectu, le paramtre spcial # est mis jour. Ex :
$ set a b c d e

=>

1 2 3 4 5

$ echo $1 $2 $# a b 5 $ $ shift 2

=> =>

abcde 123

les mots a et b sont devenus inaccessibles

$ echo $1 $3 c e $ echo $# 3 $

La commande interne shift sans argument est quivalente shift 1. Remarque : shift ne modifie pas la valeur du paramtre de position 0 qui possde une signification particulire. 2.2.4. Paramtres de position et fichiers shell Dans un fichier shell, les paramtres de position sont utiliss pour accder aux valeurs des arguments qui ont t passs lors de son appel : cela signifie quau sein du fichier shell, les occurrences de $1 sont remplaces par la valeur du premier argument, celles de $2 par la valeur du deuxime argument, etc. Le paramtre spcial $# contient le nombre darguments passs lors de lappel. Le paramtre de position 0 contient le nom complet du programme shell qui sexcute. Soit le programme shell copie :
#!/bin/bash # @(#) copie

echo "Nom du programme : $0" echo "Nb d'arguments : $#" echo "Source : $1" echo "Destination : $2" cp $1 $2

21

Pour excuter ce fichier shell : Ex :


$ chmod u+x copie $ $ copie /etc/passwd X Nom du programme : ./copie Nb d'arguments : 2 Source : /etc/passwd Destination : X $

Dans le fichier copie, chaque occurrence de $1 a t remplace par la chane de caractres /etc/passwd, celles de $2 par X. Exercice 4 : Ecrire un programme shell cp2fois prenant trois arguments : le premier dsigne le nom du fichier dont on veut copier le contenu dans deux fichiers dont les noms sont passs comme deuxime et troisime arguments. Aucun cas d'erreur ne doit tre considr. Lorsque la commande interne set est utilise lintrieur dun programme shell, la syntaxe $1 possde deux significations diffrentes : $1 comme premier argument du programme shell, et $1 comme premier paramtre de position initialis par set au sein du fichier shell. Exemple : programme shell ecrase_arg --------------# !/bin/bash echo '$1' est $1 set hello echo '$1' est $1

=> la chane $1 est remplace par le premier argument => set crase la valeur prcdente de $1

-------------Ex :

$ ecrase_arg bonjour coucou salut $1 est bonjour $1 est hello $

2.2.5. Paramtres spciaux * et @ Les paramtres spciaux @ et * contiennent tous deux la liste des valeurs des paramtres de position initialiss. Ex :
$ set un deux trois quatre $ $ echo $* un deux trois quatre $ $ echo $@ un deux trois quatre $

22

Ces deux paramtres spciaux ont des valeurs distinctes lorsque leur rfrence est place entre des guillemets ("$*" et "$@") : "$*" est remplace par "$@" est remplace par Ex :
$ set un deux trois $ $ set "$*" $ $ echo $# 1 $ $ echo $1 un deux trois $

"$1 $2 ... " "$1" "$2" ... => trois paramtres de position sont initialiss => est quivalent : set un deux trois

Lintrt de la syntaxe "$*" est de pouvoir considrer lensemble des paramtres de position initialiss comme une unique chane de caractres. La syntaxe "$@" produit autant de chanes que de paramtres de positions initialiss.
$ set un deux trois $ $ set "$@" $ $ echo $# 3 $ echo $1 un $

=> trois paramtres de position initialiss => est quivalent : set un deux trois

Variable prdfinie IFS et paramtre spcial "$*" : La variable prdfinie du shell IFS contient les caractres sparateurs de mots dans une commande. Par dfaut, ce sont les caractres espace, tabulation et interligne. Linitialisation de IFS est effectue par bash. Le shell utilise le premier caractre mmoris dans IFS (par dfaut, le caractre espace) pour sparer les diffrents paramtres de position lorsque la syntaxe "$*" est utilise. En modifiant la valeur de IFS, lutilisateur peut changer ce caractre sparateur. Ex :
$ IFS=: => le caractre deux-points est maintenant le premier caractre de IFS $ $ set un deux trois quatre $ $ echo $* un deux trois quatre $ $ echo "$@" un deux trois quatre $ $ echo "$*" => seule la forme "$*" provoque un changement un:deux:trois:quatre $

23

2.3. Suppression des ambiguts


Pour viter les ambiguts dans linterprtation des rfrences de paramtres, on utilise la syntaxe ${paramtre}. Ex :
$ x=bon $ x1=jour $ echo $x1 jour $ echo ${x}1 bon1 $

=> valeur de la variable x1 => pour concatner la valeur de la variable x la chane 1

Ex :

$ set un deux trois quatre cinq six sept huit neuf dix onze douze $ echo $11 un1 $ $ echo ${11} => pour obtenir la valeur du onzime paramtre de position onze $

2.4. Paramtres non dfinis


Trois cas peuvent se prsenter lorsque le shell doit valuer un paramtre : - le paramtre nest pas dfini, - le paramtre est dfini mais ne possde aucune valeur (valeur vide), - le paramtre possde une valeur non vide. Lorsque loption nounset de la commande interne set est positionne ltat on (commande set -o nounset), bash affiche un message derreur quand il doit valuer un paramtre non dfini. Ex :
$ set -o nounset $ $ echo $c -bash: c: unbound variable $ $ echo $1 -bash: $1: unbound variable $ $ d= $ $ echo $d $

=> option nounset ltat on


=> variable utilisateur c non dfinie,

=> message derreur !

=> d : variable dfinie mais vide => valeur null, pas derreur

La prsence de paramtres non dfinis ou dfinis mais vides dans une commande peut mener son excution lchec. Afin de traiter ce type de problme, bash fournit plusieurs mcanismes supplmentaires de substitution de paramtres. Lun deux consiste associer au paramtre une valeur ponctuelle lorsquil est non dfini ou bien dfini vide.

24

La syntaxe utiliser est la suivante : ${paramtre:-chane} Ex :


$ set -o nounset $ $ ut1=root $ ut2= $ $ echo $ut1 root $ $ echo $ut2 $ echo $1 -bash: $1: unbound variable $

=> ut1 dfinie et non vide => ut2 dfinie et vide

=> paramtre de position 1 non dfini

Avec la syntaxe mentionne ci-dessus, il est possible dassocier temporairement une valeur par dfaut aux trois paramtres. Ex :
$ echo ${ut1:-sanchis} root $ $ echo ${ut2:-sanchis} sanchis $ $ echo ${1:-sanchis} sanchis $

=> ut1 tant dfinie non vide, elle conserve sa valeur => ut2 est dfinie et vide, la valeur de remplacement est => utilise => le premier paramtre de position est non dfini

Cette association ne dure que le temps dexcution de la commande. Ex :


$ echo $1 -bash: $1: unbound variable $

=> le paramtre est redevenu indfini

La commande set +o nounset positionne loption nounset ltat off : le shell traite les paramtres non dfinis comme des paramtres vides. Ex :
$ set +o nounset $ $ echo $e $ $ echo $2

=> option nounset ltat off => variable e non dfinie, => aucune erreur signale => aucune erreur signale

$ $ f= $ echo $f $

=> f : variable dfinie vide

25

2.5. Suppression de variables


Pour rendre indfinies une ou plusieurs variables, on utilise la commande interne unset. Syntaxe : Ex : unset var [ var1 . . . ]

$ a=coucou => la variable a est dfinie $ echo $a coucou $ unset a => la variable a est supprime $ $ set -o nounset => pour afficher le message derreur $ echo $a -bash: a: unbound variable $

Une variable en lecture seule ne peut tre supprime par unset. Ex :


$ declare -r a=coucou => dfinition de la constante a $ echo $a coucou $ unset a -bash: unset: a: cannot unset: readonly variable $

26

3. Substitution de commandes
3.1. Prsentation
Syntaxe : $( cmd )

Une commande cmd entoure par une paire de parenthses () prcdes d'un caractre $ est excute par le shell puis la chane $( cmd ) est remplace par les rsultats de la commande cmd crits sur la sortie standard, cest dire lcran. Ces rsultats peuvent alors tre affects une variable ou bien servir initialiser des paramtres de position. Ex :
$ pwd /home/sanchis => rsultat crit par pwd sur sa sortie standard $ repert=$(pwd) => la chane /home/sanchis remplace la chane $(pwd) $ $ echo mon repertoire est $repert mon repertoire est /home/sanchis $

Exercice 1 : Ex :

En utilisant la substitution de commande, crire un fichier shell mach affichant : "Ma machine courante est nomdelamachine"
$ mach Ma machine courante est jade $

Lorsque la substitution de commande est utilise avec la commande interne set, lerreur suivante peut se produire :
$ set $( ls -l .bashrc) bash: set: -w: invalid option set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] $ ls -l .bashrc -rw-r--r-- 1 sanchis users 1342 nov 29 2004 .bashrc $

Le premier mot issu de la substitution commence par un caractre tiret : la commande interne set l'interprte comme une option, ce qui provoque une erreur. Pour rsoudre ce type de problme, on double le caractre tiret. Ex :
$ set -- $(ls -l .bashrc) $ $ echo $1 -rw-r--r $

Exercice 2 : Ecrire un programme shell taille qui prend un nom de fichier en argument et affiche sa taille. On ne considre aucun cas d'erreur.

27

Plusieurs commandes peuvent tre prsentes entre les parenthses. Ex :


$ pwd ; whoami /home/sanchis sanchis $ $ set $(pwd ; whoami) $ $ echo $2: $1 sanchis: /home/sanchis $

Exercice 3 :

A l'aide de la commande unix date, crire un programme shell jour qui affiche le jour courant du mois Ex :
$ date dimanche 22 octobre 2006, 18:33:38 (UTC+0200) $ $ jour 22 $

Exercice 4 :

a) Ecrire un programme shell heure1 qui affiche l'heure sous la forme heures:minutes:secondes Ex : $ heure1
18:33:38 $

b) Ecrire un programme shell heure qui n'affiche que les heures et minutes Ex : $ heure
18:33 $

Exercice 5 :

Ecrire un programme shell nbconnect connects sur la machine locale


Rq : plusieurs solutions sont possibles solution 1, avec who | wc -l solution 2, avec uptime solution 3, avec users solution 4, avec who -q

qui affiche le nombre d'utilisateurs

Les substitutions de commandes peuvent tre imbriques. Ex :


$ ls .gnome application-info gnome-vfs mime-info $ $ set $( ls $(pwd)/.gnome ) $ $ echo $# => nombre d'entres du rpertoire .gnome 3 $

28

Plusieurs sortes de substitutions (de commandes, de variables) peuvent tre prsentes dans la mme commande. Ex :
$ read rep gnome $ $ set $( ls $

$( pwd )/$rep ) => substitutions de deux commandes et d'une

=> variable

La substitution de commande permet galement de capter les rsultats crits par un fichier shell. Ex :
$ jour 22 $ $ resultat=$( jour ) $

La variable resultat contient la chane 22. Exercice 6 :


Rq :

Ecrire un programme shell uid qui affiche l'uid de l'utilisateur. On utilisera la commande unix id, la commande interne set et la variable prdfinie IFS.

Il existe pour la substitution de commande une syntaxe plus ancienne `cmd ` (deux caractres accent grave entourent la commande cmd), utiliser lorsque se posent des problmes de portabilit.

3.2. Substitutions de commandes et paramtres rgionaux


Cr par des informaticiens amricains, le systme Unix tait originellement destin des utilisateurs anglophones. La diffusion des systmes de la famille Unix (dont GNU/Linux) vers des publics de langues et de cultures diffrentes a conduit leurs dveloppeurs introduire des paramtres rgionaux (locale). Ces derniers permettent par exemple de fixer la langue d'affichage des messages, le format des dates ou des nombres. Les paramtres rgionaux se prsentent l'utilisateur sous la forme de variables prdfinies dont le nom commence par LC_. La commande unix locale utilise sans argument affiche la valeur courante de ces variables d'environnement. Ex :
$ locale LANG=fr_FR@euro LC_CTYPE="fr_FR@euro" LC_NUMERIC="fr_FR@euro" LC_TIME="fr_FR@euro" LC_COLLATE="fr_FR@euro" LC_MONETARY="fr_FR@euro" LC_MESSAGES="fr_FR@euro" LC_PAPER="fr_FR@euro" LC_NAME="fr_FR@euro" LC_ADDRESS="fr_FR@euro" LC_TELEPHONE="fr_FR@euro" LC_MEASUREMENT="fr_FR@euro" LC_IDENTIFICATION="fr_FR@euro" LC_ALL= $

29

Des commandes telles que date utilisent la valeur de ces variables prdfinies pour afficher leurs rsultats. Ex :
$ date vendredi 3 novembre 2006, 18:47:02 (UTC+0100) $

On remarque que le format du rsultat correspond bien une date la franaise (jour de la semaine, jour du mois, mois, anne). Si cette internationalisation procure un confort indniable lors d'une utilisation interactive du systme, elle pose problme lorsque l'on doit crire un programme shell se basant sur la sortie d'une telle commande, sortie qui dpend troitement de la valeur des paramtres rgionaux. La portabilit du programme shell en est fortement fragilise. Cependant, le fonctionnement standard dun systme unix traditionnel peut tre obtenu en choisissant la locale standard appele C. Pour que cette locale naffecte temporairement que les rsultats dune seule commande, par exemple date, il suffit dexcuter la commande LC_ALL=C date Ex :
$ LC_ALL=C date Fri Nov 3 18:47:41 CET 2006 $

On saperoit quavec la locale standard, le jour du mois est en troisime position alors quavec la locale prcdente, il tait en deuxime position. Pour obtenir de manire portable le jour courant du mois, on pourra excuter les commandes suivantes : Ex :
$ set $(LC_ALL=C date) ; echo $3 3 $

30

4. Caractres et expressions gnriques


Les caractres et expressions gnriques sont issus d'un mcanisme plus gnral appel expressions rationnelles (regular expressions) ou expressions rgulires. Ces caractres et expressions sont utiliss pour spcifier un modle de noms d'entres. Ce modle est ensuite interprt par le shell pour crer une liste trie de noms d'entres. Par dfaut, le shell traite uniquement les entres non caches du rpertoire courant ; cela signifie que les entres dont le nom commence par le caractre . sont ignores. Pour illustrer lutilisation des caractres et expressions gnriques, on utilisera un rpertoire appel generique contenant les 16 entres suivantes :
$ pwd /home/sanchis/generique $ $ ls -l total 0 -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users -rw-r--r-- 1 sanchis users $

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

nov nov nov nov nov nov nov nov nov nov nov nov nov nov nov nov

10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10

2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004

1 a _a A ami an Arbre e mirat En tat minuit zaza Zoulou

Rq : La valeur des paramtres rgionaux influe grandement sur la prsentation et la mthode de tri des noms on utilise la locale standard, on obtient laffichage suivant : $ LC_ALL=C total 0 -rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r-$ ls -l 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis sanchis users users users users users users users users users users users users users users users users 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov Nov 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 2004 1 A Arbre En Zoulou _a a ami an e minuit zaza ? ? ?mirat ?tat

dentres. Si

31

On saperoit que laffichage des noms dentres contenant des caractres accentus est altr. La raison de cela est que seuls les 7 premiers bits codant les caractres sont interprts en locale standard. La locale prcdente utilise un codage des caractres sur 8 bits.

4.1. Caractres gnriques


Les caractres gnriques du shell sont : * ? []

Rq : il ne faut pas confondre la syntaxe [] du mta-langage et les caractres gnriques [] du shell. Pour que bash interprte les caractres gnriques, il est ncessaire que l'option noglob de la commande interne set soit l'tat off. Pour connatre l'tat des diffrentes options de la commande interne set, on utilise la commande set o . Ex:
$ set o allexport off braceexpand on emacs on errexit off hashall on histexpand on history on ignoreeof off interactive-comments keyword off monitor on noclobber off noexec off noglob off nolog off notify off nounset off onecmd off physical off posix off privileged off verbose off vi off xtrace off $

on

Ex :

Le caractre gnrique * dsigne n'importe quelle suite de caractres, mme la chane vide

$ echo * 1 a _a A ami an Arbre e mirat En tat minuit zaza Zoulou $

Tous les noms d'entres sont affichs, tris. Ex :


$ ls -l a* -rw-r--r--rw-r--r--rw-r--r-$ 1 sanchis 1 sanchis 1 sanchis users users users 0 nov 10 11:41 a 0 nov 10 11:41 ami 0 nov 10 11:41 an

32

La notation a* dsigne toutes les entres du rpertoire courant dont le nom commence par la lettre a. Par consquent, dans la commande ls l a* le shell remplace la chane a* par la chane : a ami an En dautres termes, la commande ls "ne voit pas" le caractre * puisquil est prtrait par le shell.
$ echo *a* => noms des entres contenant un caractre a a _a ami an mirat tat zaza $

Attention :

quand aucune entre ne correspond au modle fourni, les caractres et expressions gnriques ne sont pas interprts. Ex : $ echo Z*t
Z*t $

Ex :

Le caractre gnrique ? dsigne un et un seul caractre => noms dentres composs dun seul caractre

$ echo ? 1 a A e $ $ echo ?n an En $

Plusieurs caractres gnriques diffrents peuvent tre prsents dans un modle. Ex :


$ echo ?mi* ami mirat $

Exercice : Exercice :

Ecrire un modle permettant d'afficher le nom des entres dont le 2me caractre est un a. Ecrire un modle permettant d'afficher le nom des entres dont le 1er caractre est un a suivi par 2 caractres quelconques. Les caractres gnriques [] dsignent un seul caractre parmi un groupe de caractres

Ce groupe est prcis entre les caractres []. Il peut prendre deux formes : la forme ensemble et la forme intervalle. Forme ensemble : tous les caractres souhaits sont explicitement mentionns entre [] Ex :
$ ls -l [ame] -rw-r--r-1 sanchis -rw-r--r-1 sanchis $ $ echo ?[ame]* _a ami mirat zaza $ users users 0 nov 10 11:41 a 0 nov 10 11:41 e

Le modle [ame] dsigne tous les noms d'entres constitus d'un seul caractre a, m ou e.

33

Forme intervalle : seules les bornes de l'intervalle sont prcises et spares par un - . Ex :
$ 1 $ $ a $ $ A $ echo * a _a A ami an Arbre e mirat En tat minuit zaza Zoulou echo [a-z]* => le caractre Z est ignor A ami an Arbre e mirat En tat minuit zaza echo [A-Z]* => le caractre a est ignor Arbre e mirat En tat minuit zaza Zoulou

Linterprtation du modle [a-z] est conditionne par la valeur des paramtres rgionaux : cette syntaxe est donc non portable et il est dconseill de lemployer car elle peut avoir des effets nfastes lorsquelle est utilise avec la commande unix rm. Si l'on souhaite dsigner une classe de caractres tels que les minuscules ou les majuscules, il est prfrable d'utiliser la syntaxe POSIX 1003.2 correspondante. Ce standard dfinit des classes de caractres sous la forme [:nom_classe:] Des exemples de classes de caractres dfinies dans ce standard sont : [:upper:] (majuscules) [:lower:] (minuscules) [:digit:] (chiffres, 0 9) [:alnum:] (caractres alphanumriques). Attention : Ex : pour dsigner n'importe quel caractre d'une classe, par exemple les minuscules, on place la classe entre les caractres gnriques []. => noms d'entres constitus d'une seule minuscule

$ a $ $ A $

echo [[:lower:]] e echo [[:upper:]]* Arbre En Zoulou

Pour afficher les noms d'entres commenant par une majuscule ou le caractre a :
echo [[:upper:]a]*

Il est possible de mentionner un caractre ne devant pas figurer dans un groupe de caractres. Il suffit de placer le caractre ! juste aprs le caractre [. Ex :
$ echo _a ami $ $ echo 1 A $ $ echo 1 a _a $ $ echo ami an $ ?[!n]* => noms d'entres ne comportant pas le caractre n en 2 Arbre mirat tat minuit zaza Zoulou [![:lower:]] [![:upper:]]* ami an e mirat tat minuit zaza [![:upper:]]*[!at]
me

position

34

4.2. Expressions gnriques


Pour que bash, interprte les expressions gnriques, il est ncessaire que loption extglob de la commande interne shopt soit active. Ex :
$ shopt cdable_vars off cdspell off checkhash off checkwinsize on cmdhist on dotglob off execfail off expand_aliases on extdebug off extglob off extquote on failglob off force_fignore on gnu_errfmt off histappend off histreedit off histverify off hostcomplete on huponexit off interactive_comments on lithist off login_shell on mailwarn off no_empty_cmd_completion off nocaseglob off nocasematch off nullglob off progcomp on promptvars on restricted_shell off shift_verbose off sourcepath on xpg_echo off $

Pour activer une option de la commande interne shopt on utilise la commande : shopt s opt Pour activer le traitement des expressions gnriques par le shell : shopt s extglob Les expressions gnriques de bash sont : ? (liste_modles) : * (liste_modles) : + (liste_modles) : @ (liste_modles) : ! (liste_modles) : correspond 0 ou 1 occurrence de chaque modle correspond 0,1 ou plusieurs occurrences de chaque modle correspond au moins 1 occurrence de chaque modle correspond exactement 1 occurrence de chaque modle correspond tout sauf aux modles mentionns

35

Ex :

$ echo +([[:lower:]]) bash: syntax error near unexpected token `(' $ $ shopt -s extglob $ $ echo +([[:lower:]]) => noms constitus que de minuscules a ami an e mirat tat minuit zaza $ $ echo !(+([[:lower:]])) 1 _a A Arbre En Zoulou $

Exercice :

Ecrire un modle correspondant aux noms d'entres ne comportant pas de caractre a

Si lon souhaite utiliser les expressions gnriques dans un fichier shell, on y inclura pralablement la commande shopt s extglob Remarques : Outre extglob, dautres options de la commande interne shopt permettent de modifier la cration de la liste des noms dentres. Ces options sont : dotglob, nocaseglob, nullglob, failglob. Par dfaut elles sont inactives (off). Pour grer ses propres options, bash intgre deux commandes, set et shopt. Dun point de vue pratique, pour connatre l'tat des options de la commande interne set : set o pour activer une option de la commande interne set : set o option pour dsactiver une option de la commande interne set : set +o option pour connatre l'tat des options de la commande interne shopt : shopt pour activer une option de la commande interne shopt : shopt -s option pour dsactiver une option de la commande interne shopt : shopt -u option

36

5. Redirections lmentaires
5.1. Descripteurs de fichiers
Un processus Unix possde par dfaut trois voies dinteraction avec lextrieur appeles entres / sorties standard identifies par un entier positif ou nul appel descripteur de fichier. Ces entres / sorties standard sont : - une entre standard , de descripteur 0 - une sortie standard , de descripteur 1 - une sortie standard pour les messages derreurs, de descripteur 2. Toute commande tant excute par un processus, nous dirons galement quune commande possde trois entres / sorties standard. 1 0

commande 2

De manire gnrale, une commande de type filtre (ex : cat) prend ses donnes sur son entre standard qui correspond par dfaut au clavier, affiche ses rsultats sur sa sortie standard, par dfaut lcran, et affiche les erreurs ventuelles sur sa sortie standard pour les messages derreurs, par dfaut lcran galement.

5.2. Redirections lmentaires


On peut rediriger sparment chacune des trois entres/sorties standard dune commande. Cela signifie quune commande pourra - lire les donnes traiter partir dun fichier et non du clavier de lutilisateur - crire les rsultats ou erreurs dans un fichier et non lcran. Redirection de la sortie standard : Ex :
$ pwd /home/sanchis $ pwd > fich $ $ cat fich /home/sanchis $

> fichier ou 1> fichier

=> aucun rsultat affich lcran ! => le rsultat a t enregistr dans le fichier fich

Cette premire forme de redirection de la sortie standard crase l'ancien contenu du fichier de sortie (fichier fich) si celui-ci existait dj, sinon le fichier est cr. Le shell prtraite une commande avant de lexcuter : dans lexemple ci-dessous, le shell cre un fichier vide f devant recevoir les rsultats de la commande (ici inexistante) ; lunique effet de >f sera donc la cration du fichier f ou sa remise zro.

37

Ex :

$ >f $ $ ls -l f -rw-r--r-$

=> cre ou remet zro le fichier f


1 sanchis users 0 oct 22 11:34 f

Une commande ne possde quune seule sortie standard; par consquent, si on dsire effacer le contenu de plusieurs fichiers, il est ncessaire dutiliser autant de commandes que de fichiers effacer. Le caractre ; permet dexcuter squentiellement plusieurs commandes crites sur la mme ligne. Ex :
$ $ > f1 ; >f2

La redirection de la sortie standard de cat est souvent utilise pour affecter un contenu succinct un fichier. Ex :
$ cat >tata => lentre standard est directement recopie dans tata a demain si vous le voulez bien ^D $ $ cat tata a demain si vous le voulez bien $

0 a demain si vous le voulez bien

cat

tata
Pour concatner (cest dire ajouter la fin) la sortie standard d'une commande au contenu d'un fichier, une nouvelle forme de redirection doit tre utilise : >> fichier Ex :
$ pwd > t $ $ date >> t $ $ cat t /home/sanchis lundi 20 novembre 2006, 15:27:41 (UTC+0100) $

Comme pour la redirection prcdente, lexcution de >> fich cre le fichier fich sil nexistait pas. Redirection de la sortie standard pour les messages d'erreur : 2> fichier

On ne doit laisser aucun caractre espace entre le chiffre 2 et le symbole >.

38

Ex :

$ pwd /home/sanchis $ ls vi => lditeur de texte vi se trouve dans le rpertoire /usr/bin ls: vi: Aucun fichier ou rpertoire de ce type $ ls vi 2> /dev/null $

Le fichier spcial /dev/null est appel poubelle ou puits car toute sortie qui y est redirige, est perdue. En gnral, il est utilis lorsquon est davantage intress par le code de retour de la commande plutt que par les rsultats ou messages derreur quelle engendre. Comme pour la sortie standard, il est possible de concatner la sortie standard pour les messages derreur d'une commande au contenu d'un fichier : 2>> fichier Ex :
$ ls vi ls: vi: Aucun fichier ou rpertoire de ce type $ $ ls vi 2>err $ $ ls date 2>>err $ $ cat err ls: vi: Aucun fichier ou rpertoire de ce type ls: date: Aucun fichier ou rpertoire de ce type $

Pour rediriger la sortie standard pour les messages derreur vers la sortie standard (c.a.d vers le fichier de descripteur 1), on utilisera la syntaxe : 2>&1 Cela est souvent utilis lorsquon dsire conserver dans un mme fichier toutes les sorties. Ex :
$ ls Mail err public_html _.forward fic_noms t $ $ ls vi err >trace 2>&1 $ $ cat trace ls: vi: Aucun fichier ou rpertoire de ce type err $ tmp

La sortie standard est redirige vers le fichier trace [a] puis la sortie standard pour les messages derreur est redirige vers la sortie standard, c.--d. galement vers le fichier trace [b].
ls vi err 2 trace 1 Ecran

[a]

39

ls vi err 2

Ecran

trace

[b] La syntaxe &> fichier est quivalente la syntaxe > fichier 2>&1 Ex :
$ ls vi err &> trace $ $ cat trace ls: vi: Aucun fichier ou rpertoire de ce type err $

Attention : Exercice :

Les redirections tant traites de gauche droite, lordre des redirections est important. Que fait la commande :
ls vi fic_noms 2>&1 >trace

Redirection de l'entre standard : Ex :


$ $ mail sanchis < lettre

< fichier

La commande mail envoie lutilisateur sanchis le contenu du fichier lettre. Une substitution de commande associe une redirection de lentre standard permet daffecter une variable le contenu dun fichier. En effet, la substitution de commande $(cat fichier) peut tre avantageusement remplace par la syntaxe $(< fichier). Cette deuxime forme est plus rapide. Ex :
$ cat fic_noms pierre beteille anne debazac julie donet $ $ liste=$(<fic_noms) $ $ echo $liste => liste est une variable et non un fichier ! pierre beteille anne debazac julie donet => elle contient le contenu du $ => fichier fic_noms

Redirections spares des entres / sorties standard : Les entres / sorties peuvent tre rediriges indpendamment les unes des autres.

40

Ex :

$ wc -l <fic_noms $ $ cat fic_nblignes 3 $ $ cat err $

>fic_nblignes

2>err

La commande unix wc -l affiche le nombre de lignes dun ou plusieurs fichiers texte. Ici, il sagit du nombre de lignes du fichier fic_noms. Le fichier err est cr mais est vide car aucune erreur ne sest produite. Dans cet exemple, la disposition des redirections dans la ligne de commande na pas dimportance, car les deux sorties ne sont pas rediriges vers le mme fichier. Il est possible de placer les redirections o l'on souhaite car le shell traite les redirections avant d'excuter la commande : Ex :
$ < fic_noms > fic_nblignes $ $ cat fic_nblignes 3 $ $ cat err $ wc 2>err -l

La plupart des commandes affichent leurs rsultats sous la mme forme, suivant que lon passe en argument le nom dun fichier ou que lon redirige son entre standard avec ce fichier. Ex :
$ cat fic bonjour et au revoir $ $ cat <fic bonjour et au revoir $

=> cat ouvre le fichier fic afin de lire son contenu

=> cat lit son entre standard (redirige par le shell)

Il nen est pas ainsi avec la commande wc : celle-ci ncrit pas les rsultats de la mme manire. Ex :
$ wc -l fic_noms 3 fic_noms $ $ wc -l < fic_noms 3 $

Par consquent, lorsque lon dsirera traiter la sortie dune commande wc, il faudra prendre garde la forme utilise. La deuxime forme est prfrable lorsque on ne souhaite que le nombre de lignes. Ex :
$ nblignes=$( wc -l < fic_noms ) $ $ echo $nblignes => nombre de lignes 3 $

41

Texte joint : Il existe plusieurs syntaxes lgrement diffrentes pour passer un texte joint comme entre une commande. Nanmoins, la syntaxe prsente ci-dessous est la plus simple. Syntaxe : cmd <<mot texte mot

Lutilisation de cette syntaxe permet dalimenter lentre standard de la commande cmd laide dun contenu texte dlimit par deux balises mot. Aucun caractre espace ne doit tre prsent entre << et mot. Ex :
$ a=3.5 b=1.2 $ $ bc <<EOF > $a + $b > EOF 4.7 $

La commande unix bc est une calculatrice utilisable en ligne de commande. Dans lexemple cidessus, deux variables a et b sont initialises respectivement avec les chanes de caractres 3.5 et 1.2. Le shell effectue les deux substitutions de variables prsentes entre les mots EOF puis alimente lentre standard de bc avec le texte obtenu. Cette commande calcule la valeur de lexpression fournie puis affiche son rsultat sur sa sortie standard. Fermeture des entres / sorties standard : Fermeture de lentre standard : <&Fermeture de la sortie standard : >&Fermeture de la sortie standard pour les messages derreur : Ex :

2>&-

$ >&echo coucou -bash: echo: write error: Mauvais descripteur de fichier $ $

Il y a fermeture de la sortie standard puis une tentative dcriture sur celle-ci : lerreur est signale par linterprteur de commandes.

5.3. Tubes
Le mcanisme de tube (symbolis par le caractre |) permet denchaner lexcution de commandes successives en connectant la sortie standard dune commande lentre standard de la commande suivante : Ex :
ls -l /bin | more

Il y a affichage du contenu du rpertoire /bin (commande ls -l /bin) cran par cran (commande more). En effet, les informations affiches par ls -l sont envoyes vers lentre de la commande 42

more qui les affiche cran par cran. La sortie standard de la dernire commande ntant pas redirige, laffichage final seffectue lcran.
ls -l /bin 2 1 | 0 more 2 1

Un rsultat quivalent aurait pu tre obtenu dune manire moins lgante en excutant la suite de commandes :
ls -l /bin >temporaire ; more < temporaire ; rm temporaire

La commande ls -l /bin crit le rsultat dans le fichier temporaire ; ensuite, on affiche cran par cran le contenu de ce fichier ; enfin, on efface ce fichier devenu inutile. Le mcanisme de tube vite lutilisateur de grer ce fichier intermdiaire. Pipelines : On appelle pipeline, une suite non vide de commandes connectes par des tubes : cmd1 | ... | cmdn Chaque commande est excute par un processus distinct, la sortie standard de la commande cmdi-1 tant connecte lentre standard de la commande cmdi . Ex :
$ date | tee trace1 trace2 | wc -l 1 => date ncrit ses rsultats que sur une seule ligne $ $ cat trace1 lundi 20 novembre 2006, 15:37:49 (UTC+0100) $ $ cat trace2 lundi 20 novembre 2006, 15:37:49 (UTC+0100) $

La commande unix tee crit le contenu de son entre standard sur sa sortie standard tout en gardant une copie dans le ou les fichiers dont on a pass le nom en argument. Dans lexemple ci-dessus, tee crit le rsultat de date dans les fichiers trace1 et trace2 ainsi que sur sa sortie standard, rsultat pass la commande wc -l.

43

6. Groupement de commandes
Le shell fournit deux mcanismes pour grouper lexcution dun ensemble de commandes sans pour cela affecter un nom ce groupement : - linsertion de la suite de commandes entre une paire daccolades - linsertion de cette suite de commandes entre une paire de parenthses. { suite_cmds ; } Insre entre une paire daccolades, la suite de commandes est excute dans le shell courant. Cela a pour effet de prserver les modifications apportes par la suite de commandes sur lenvironnement du processus courant. Ex :
$ pwd /home/sanchis => rpertoire initial $ $ { cd /bin ; pwd ; } => changement du rpertoire courant /bin $ $ pwd /bin => rpertoire final (le changement a t prserv !) $

Sexcutant dans le shell courant, les modifications apportes aux variables sont galement conserves : Ex :
$ a=bonjour $ $ { a=coucou ; echo $a coucou $ $ echo $a coucou $

;}

Les accolades { et } sont deux mots-cl de bash ; chacune delles doit donc tre le premier mot dune commande. Pour cela, chaque accolade doit tre le premier mot de la ligne de commande ou bien tre prcde dun caractre ;. De plus, suite_cmds ne doit pas coller laccolade ouvrante {. Par contre, la prsence ou absence dun caractre espace entre le caractre ; et le mot-cl } na aucune importance. Ex :
$ { cd /bin } => laccolade } nest pas le premier mot dune commande > => le shell ne dtecte pas la fin du groupement > ^C => control-C $ $ {cd /bin ;} => il manque un espace ou une tabulation entre { et cd -bash: syntax error near unexpected token `}' $

44

Toutefois, lance en arrire-plan, la suite de commandes nest plus excute par le shell courant mais par un sous-shell. Ex :
$ pwd /home/sanchis => rpertoire initial $ $ { echo processus : ; cd / ; ps ;} & processus : [1] 27963 $ PID TTY TIME CMD 27942 pts/14 00:00:00 bash 27947 pts/14 00:00:00 bash 27963 pts/14 00:00:00 ps [1] + Done $ $ pwd /home/sanchis $ { echo processus :; cd /; ps; }

=> rpertoire final

Bien quune commande cd / ait t excute, le rpertoire courant na pas t modifi (/home/sanchis). Une utilisation frquente du regroupement de commandes est la redirection globale de leur entre ou sortie standard. Ex :
$ cat fich premiere ligne deuxieme ligne troisieme ligne quatrieme ligne $ $ { read ligne1 ; read ligne2 => le caractre > est affich par le shell, indiquant > } < fich $ => que laccolade } est manquante $ echo $ligne1 premiere ligne $ echo $ligne2 deuxieme ligne $

Lentre standard des deux commandes read ligne1 et read ligne2 est globalement redirige : elles liront squentiellement le contenu du fichier fich. Si les commandes de lecture navaient pas t groupes, seule la premire ligne de fich aurait t lue. Ex :
$ read ligne1 < fich ; read ligne2 < fich $ $ echo $ligne1 premiere ligne $ $ echo $ligne2 premiere ligne $

45

Comme pour toutes commandes composes, lorsque plusieurs redirections de mme type sont appliques la mme suite de commandes, seule la redirection la plus proche est effective. Ex :
$ { read lig1 ; read -p "Entrez votre ligne : " lig2 </dev/tty > read lig3 > } < fich Entrez votre ligne : bonjour tout le monde $ $ echo $lig1 premiere ligne $ echo $lig2 bonjour tout le monde $ echo $lig3 deuxieme ligne $

Les commandes read lig1 et read lig3 lisent le contenu du fichier fich mais la commande read -p "Entrez votre ligne : " lig2 lit son entre standard (/dev/tty). (suite_cmds) Insre entre une paire de parenthses, la suite de commandes est excute dans un sous-shell. Lenvironnement du processus nest pas modifi aprs excution de la suite de commandes. Les parenthses sont des oprateurs (et non des mots cl) : suite_cmds peut par consquent coller une ou deux parenthses sans provoquer une erreur de syntaxe. Ex :
$ pwd /home/sanchis => rpertoire initial $ $ (cd /bin ; pwd) /bin $ $ pwd /home/sanchis => le rpertoire initial na pas t modifi $ $ b=bonjour $ $ ( b=coucou ; echo $b ) coucou $ $ echo $b => la valeur de la variable b na pas t modifie bonjour $

Ce type de groupement de commandes peut tre aussi utilis pour effectuer une redirection globale. Ex :
$ ( pwd ; date ; echo FIN ) > fin $ $ cat fin /home/sanchis lundi 20 novembre 2006, 15:47:45 (UTC+0100) FIN $

46

7. Code de retour 4
Un code de retour (exit status) est fourni par le shell aprs excution d'une commande. Le code de retour est un entier positif ou nul, compris entre 0 et 255, indiquant si l'excution de la commande s'est bien droule ou s'il y a eu un problme quelconque. Par convention, un code de retour gal 0 signifie que la commande s'est excute correctement. Un code diffrent de 0 signifie une erreur syntaxique ou d'excution. Lvaluation du code de retour est essentielle lexcution de structures de contrle du shell telles que if et while.

7.1. Paramtre spcial ?


Le paramtre spcial ? ( ne pas confondre avec le caractre gnrique ?) contient le code de retour de la dernire commande excute de manire squentielle (excution synchrone). Ex :
$ pwd /home/sanchis $ echo $? 0 => la commande pwd s'est excute correctement $ ls -l vi ls: vi: Aucun fichier ou rpertoire de ce type $ echo $? 2 => une erreur sest produite ! $

Exercice :

En utilisant la commande unix ls et le mcanisme de redirection, crire un programme shell dansbin prenant un nom de commande en argument et qui affiche 0 si cette commande est prsente dans /bin, une valeur diffrente de 0 sinon. Ex :
$ dansbin 0 $ dansbin 2 $ ls who

Chaque commande positionne sa manire les codes de retour diffrents de 0. Ainsi, un code de retour gal 1 positionn par la commande unix ls n'a pas la mme signification qu'un code de retour 1 positionn par la commande unix grep. Les valeurs et significations du code de retour dune commande unix ou du shell sont documentes dans les pages correspondantes du manuel (ex : man grep). Lorsque une commande est excute en arrire-plan (excution asynchrone), son code de retour n'est pas mmoris dans le paramtre spcial ?.

Ce texte est paru sous une forme lgrement diffrente dans la revue Linux Magazine France , n39, mai 2002

47

Ex :

$ pwd => mise zro du paramtre spcial ? /home/sanchis $ $ echo $? 0 $ ls -l vi & => commande excute en arrire-plan [1] 19331 $ ls: vi: Aucun fichier ou rpertoire de ce type [1]+ Exit 2 $ $ echo $? 0 $ ls --color=tty -l vi

On remarque que la commande s'est termine avec la valeur 2 (Exit 2) mais que ce code de retour n'a pas t enregistr dans le paramtre ?. La commande interne deux-points (:) sans argument retourne toujours un code de retour gal 0. Ex :
$ : $ echo $? 0 $

=> commande deux-points

Il en est de mme avec la commande interne echo : elle retourne toujours un code de retour gal 0, sauf cas particuliers. Ex :
$ 1>&- echo coucou -bash: echo: write error: Mauvais descripteur de fichier $ $ echo $? 1 $

Enfin, certaines commandes utilisent plusieurs valeurs pour indiquer des significations diffrentes, comme la commande unix grep. Commande unix grep :

Cette commande affiche sur sa sortie standard l'ensemble des lignes contenant une chane de caractres spcifie en argument, lignes appartenant un ou plusieurs fichiers texte (ou par dfaut, son entre standard). La syntaxe de cette commande est : grep [ option(s) ] chane_cherche [ fich_texte1 ... ]

Soit le fichier pass contenant les cinq lignes suivantes :


root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bertrand:x:101:100::/home/bertrand:/bin/bash albert:x:102:100::/home/albert:/bin/bash sanchis:x:103:100::/home/sanchis:/bin/bash

48

La commande ci-dessous affiche toutes les lignes du fichier pass contenant la chane sanchis. Ex :
$ grep sanchis pass sanchis:x:103:100::/home/sanchis:/bin/bash $

Attention : Ex :

grep recherche une chane de caractres et non un mot.


$ grep bert pass bertrand:x:101:100::/home/bertrand:/bin/bash albert:x:102:100::/home/albert:/bin/bash $

La commande affiche toutes les lignes contenant la chane bert (et non le mot bert). Si lon souhaite la chane cherche en dbut de ligne, on utilisera la syntaxe ^chane_cherche. Si on la veut en fin de ligne : chane_cherche$ Ex :
$ grep ^bert pass bertrand:x:101:100::/home/bertrand:/bin/bash $

La commande unix grep positionne un code de retour - gal 0 pour indiquer qu'une ou plusieurs lignes ont t trouves - gal 1 pour indiquer qu'aucune ligne n'a t trouve - gal 2 pour indiquer la prsence d'une erreur de syntaxe ou qu'un fichier mentionn en argument est inaccessible. Ex :
$ grep sanchis pass sanchis:x:103:100::/home/sanchis:/bin/bash $ echo $? 0 $ $ grep toto pass $ $ echo $? => la chane toto n'est pas prsente dans pass 1 $ $ grep sanchis turlututu grep: turlututu: Aucun fichier ou rpertoire de ce type $ $ echo $? => le fichier turlututu n'existe pas ! 2 $

Exercice :

Ecrire un programme shell connu prenant en argument un nom dutilisateur qui affiche 0 sil est enregistr dans le fichier pass, 1 sinon. Ex :
$ connu bert 1 $ connu albert 0 $

49

7.2. Code de retour d'un programme shell


Le code de retour d'un programme shell est le code de retour de la dernire commande qu'il a excute. Soit le programme shell lvi contenant l'unique commande ls vi.
#!/bin/bash # @(#) ls vi lvi

Cette commande produira une erreur car vi ne se trouve pas dans le rpertoire courant ; aprs excution, le code de retour de lvi sera de celui de la commande ls vi (dernire commande excute). Ex :
$ lvi ls: vi: Aucun fichier ou rpertoire de ce type $ $ echo $? 2 => code de retour de la dernire commande excute par lvi $ => c.--d. ls vi

Autre exemple avec le programme shell lvi1 de contenu :


#!/bin/bash # @(#) ls vi echo Fin lvi1

La dernire commande excute par lvi1 sera la commande interne echo qui retourne un code de retour gal 0. Ex :
$ lvi1 ls: vi: Aucun fichier ou rpertoire de ce type Fin $ $ echo $? 0 => code de retour de la dernire commande excute par lvi (echo Fin) $

Il est parfois ncessaire de positionner explicitement le code de retour d'un programme shell avant qu'il ne se termine : on utilise alors la commande interne exit.

7.3. Commande interne exit


Syntaxe : exit [ n ]

Elle provoque l'arrt du programme shell avec un code de retour gal n. Si n n'est pas prcis, le code de retour fourni est celui de la dernire commande excute.

50

Soit le programme shell lvi2 :


#!/bin/bash # @(#) ls vi exit 23 lvi2

Ex :

$ lvi2 ls: vi: Aucun fichier ou rpertoire de ce type $ $ echo $? 23 => code de retour de exit 23 $

Le code de retour renvoy par ls vi est 2 ; en utilisant la commande interne exit, le programme shell lvi2 positionne un code de retour diffrent (23).

7.4. Code de retour d'une suite de commandes


Le code de retour d'une suite de commandes est le code de retour de la dernire commande excute. Le code de retour de la suite de commandes cmd1 ; cmd2 ; cmd3 est le code de retour de la commande cmd3. Ex :
$ pwd ; ls vi ; echo bonjour /home/sanchis ls: vi: Aucun fichier ou rpertoire de ce type bonjour $ echo $? 0 => code de retour de echo bonjour $

Il en est de mme pour le pipeline cmd1 | cmd2 | cmd3. Le code de retour sera celui de cmd3. Ex :
$ cat pass | grep sanchis sanchis:x:103:100::/home/sanchis:/bin/bash $ $ echo $? 0 => code de retour de grep sanchis $

Il est possible d'obtenir la ngation d'un code de retour d'un pipeline en plaant le mot-cl ! devant celui-ci. Cela signifie que si le code de retour de pipeline est gal 0, alors le code de retour de ! pipeline est gal 1. Ex :
$ ! ls pass => le code de retour de ls passest gal 0 pass $ $ echo $? 1 $ $ ! cat pass | grep daemon

51

daemon:x:1:1:daemon:/usr/sbin:/bin/sh $ $ echo $? 1 $

Inversement, si le code de retour de pipeline est diffrent de 0, alors celui de ! pipeline est gal 0. Ex :
$ ! grep sanchis turlututu grep: turlututu: Aucun fichier ou rpertoire de ce type $ $ echo $? 0 $

7.5. Rsultats et code de retour


On ne doit pas confondre le rsultat d'une commande et son code de retour : le rsultat correspond ce qui est crit sur sa sortie standard ; le code de retour indique uniquement si l'excution de la commande s'est bien effectue ou non. Parfois, on est intress uniquement par le code de retour d'une commande et non par les rsultats qu'elle produit sur la sortie standard ou la sortie standard pour les messages d'erreurs. Ex :
$ grep toto pass > /dev/null 2>&1 => ou bien : grep toto pass &>/dev/null $ $ echo $? 1 => on en dduit que la chane toto n'est pas prsente dans pass $

7.6. Oprateurs && et || sur les codes de retour


Les oprateurs && et || autorisent lexcution conditionnelle dune commande cmd suivant la valeur du code de retour de la dernire commande prcdemment excute. Oprateur : && Syntaxe : cmd1 && cmd2

Le fonctionnement est le suivant : cmd1 est excute et si son code de retour est gal 0, alors cmd2 est galement excute. Ex :
$ grep daemon pass && echo daemon existe daemon:x:1:1:daemon:/usr/sbin:/bin/sh daemon existe $

La chane de caractres daemon est prsente dans le fichier pass, le code de retour renvoy par lexcution de grep est 0 ; par consquent, la commande echo daemon existe est excute.

52

Oprateur : || Syntaxe : cmd1 || cmd2

cmd1 est excute et si son code de retour est diffrent de 0, alors cmd2 est galement excute. Pour illustrer cela, supposons que le fichier toto nexiste pas. Ex :
$ ls pass toto ls: toto: Aucun fichier ou rpertoire de ce type pass $ $ rm toto || echo toto non efface rm: ne peut enlever `toto': Aucun fichier ou rpertoire de ce type toto non efface $

Le fichier toto nexistant pas, la commande rm toto affiche un message derreur et produit un code de retour diffrent de 0 : la commande interne echo qui suit est donc excute. Combinaisons doprateurs && et || Les deux rgles mentionnes ci-dessus sont appliques par le shell lorsqu'une suite de commandes contient plusieurs oprateurs && et ||. Ces deux oprateurs ont mme priorit et leur valuation seffectue de gauche droite. Ex :
$ ls pass || ls toto || echo fini aussi pass $

Le code de retour de ls pass est gal 0 car pass existe, la commande ls toto ne sera donc pas excute. Dautre part, le code de retour de lensemble ls pass || ls toto est le code de retour de la dernire commande excute, cest dire est gal 0 (car cest le code de retour de ls pass), donc echo fini aussi nest pas excute. Intervertissons maintenant les deux commandes ls : Ex :
$ ls toto || ls pass || echo fini ls: toto: Aucun fichier ou rpertoire de ce type pass $

Le code de retour de ls toto est diffrent de 0, donc ls pass sexcute. Cette commande renvoie un code de retour gal 0, par consquent echo fini nest pas excute. Combinons maintenant oprateurs && et || : Ex :
$ ls pass || ls toto || echo suite et && echo fin pass fin $

53

La commande ls pass est excute avec un code de retour gal 0, donc la commande ls toto nest pas excute : le code de retour de lensemble ls pass || ls toto est gal 0, la commande echo suite et nest pas excute. Le code de retour de ls pass || ls toto || echo suite et est gal 0, donc la commande echo fin est excute ! Bien sr, un raisonnement analogue sapplique avec loprateur && : Ex :

$ ls pass pass ls: toto: $ $ ls toto ls: toto: $ $ ls pass pass ls: toto: fin $

&& ls toto && echo fini Aucun fichier ou rpertoire de ce type && ls pass && echo suite et && echo fin Aucun fichier ou rpertoire de ce type && ls toto && echo suite et || echo fin Aucun fichier ou rpertoire de ce type

54

8. Structures de contrle case et while


8.1. Choix multiple case
Syntaxe : case mot in [ modle [ | modle ] ... ) suite_de_commandes ;; ] ... esac

Le shell value la valeur de mot puis compare squentiellement cette valeur chaque modle. Ds qu'un modle correspond la valeur de mot, la suite de commandes associe est excute, terminant l'excution de la commande interne compose case. Les mots case et esac sont des mots-cl ce qui signifie que chacun deux doit tre le premier mot dune commande. suite_de_commandes doit se terminer par deux caractres point-virgule colls, de manire ce quil ny ait pas dambigut avec lenchanement squentiel de commandes cmd1 ; cmd2. Un modle peut tre construit laide des caractres et expressions gnriques de bash [cf. Caractres et expressions gnriques]. Dans ce contexte, le symbole | signifie OU. Pour indiquer le cas par dfaut, on utilise le modle *. Ce modle doit tre plac la fin de la structure de contrle case. Le code de retour de la commande compose case est celui de la dernire commande excute de suite_de_commandes. Exemple 1 : programme shell oui affichant OUI si lutilisateur a saisi le caractre o ou O
#!/bin/bash # @(#) oui rep

read p Entrez votre rponse : case $rep in o|O ) echo OUI ;; *) echo Indefini esac

Rq : Exemple 2 :

il nest pas obligatoire de terminer par ;; la dernire suite_de_commandes programme shell nombre prenant une chane de caractres en argument et qui affiche cette chane si elle est constitue dune suite de chiffres
#!/bin/bash # @(#) nombre

shopt -s extglob case $1 in +([[:digit:]]) ) echo $1 est une suite de chiffres ;; esac

55

Exercice :

Ecrire un programme shell 4arg qui vrifie que le nombre d'arguments passs lors de lappel du programme est gal 4 et crit suivant le cas le message Correct ou le message Erreur. Ecrire un programme shell reconnaitre qui demande lutilisateur dentrer un mot, puis suivant le premire caractre de ce mot, indique sil commence par un chiffre, une minuscule, une majuscule ou une autre sorte de caractre. En utilisant la commande unix date et la locale standard [cf. Substitution de commandes], crire un programme datefr qui affiche la date courante de la manire suivante : mercredi 5 janvier 2005 10:00

Exercice :

Exercice :

8.2. Itration while


La commande interne while correspond litration tant que prsente dans de nombreux langages de programmation. Syntaxe : while suite_cmd1 do suite_cmd2 done

La suite de commandes suite_cmd1 est excute; si son code de retour est gal 0, alors la suite de commandes suite_cmd2 est excute, puis suite_cmd1 est re-excute. Si son code de retour est diffrent de 0, alors litration se termine. En dautres termes, suite_cmd2 est excute autant de fois que le code de retour de suite_cmd1 est gal zro. Loriginalit de cette structure de contrle est que le test ne porte pas sur une condition boolenne (vraie ou fausse) mais sur le code de retour issu de lexcution dune suite de commandes. En tant que mots-cl, while, do et done doivent tre les premiers mots d'une commande. Une commande while, comme toute commande interne, peut tre crite directement sur la ligne de commande. Ex :
$ while who | grep sanchis >/dev/null > do > echo lutilisateur sanchis est encore connecte > sleep 5 > done lutilisateur sanchis est encore connecte ^C $

56

Le fonctionnement est le suivant : la suite de commandes who | grep sanchis est excute. Son code de retour sera gal 0 si le mot sanchis est prsent dans les rsultats engendrs par lexcution de la commande unix who, cest dire si lutilisateur sanchis est connect. Dans ce cas, la ou les lignes correspondant cet utilisateur seront affiches sur la sortie standard de la commande grep. Comme seul le code de retour est intressant et non le rsultat, la sortie standard de grep est redirige vers le puits (/dev/null). Enfin, le message est affich et le programme sendort pendant 5 secondes. Ensuite, la suite de commandes who | grep sanchis est r excute. Si lutilisateur sest totalement dconnect, la commande grep ne trouve aucune ligne contenant la chane sanchis, son code de retour sera gal 1 et le programme sortira de litration. Commandes internes while et deux-points La commande interne deux-points associe une itration while compose rapidement un serveur (dmon) rudimentaire. Ex :
$ while : > do > who | cut -d' ' -f1 >>fic > sleep 300 > done & [1] 12568 $

=> boucle infinie => traitement effectuer => temporisation

Lecture du contenu dun fichier texte La commande interne while est parfois utilise pour lire le contenu dun fichier texte. La lecture seffectue alors ligne par ligne. Il suffit pour cela : - de placer une commande interne read dans suite_cmd1 - de placer les commandes de traitement de la ligne courante dans suite_cmd2 - de rediriger lentre standard de la commande while avec le fichier lire. Syntaxe : while read [ var1 ... ] do commande(s) de traitement de la ligne courante done < fichier__lire

Exemple : programme wh qui affiche les noms des utilisateurs connects


#!/bin/bash # @(#) wh

who > tmp while read nom reste do echo $nom done < tmp rm tmp

57

Exercice :

On dispose dun fichier personnes dont chaque ligne est constitue du prnom et du genre (m pour masculin, f pour fminin) dun individu. Ex :
$ cat personnes arthur m pierre m dominique f paule f sylvie f jean m $

Ecrire un programme shell tripersonnes qui cre partir de ce fichier, un fichier garcons contenant uniquement les prnoms des garons et un fichier filles contenant les prnoms des filles. Ex :

$ tripersonnes $ $ cat filles dominique paule sylvie $ $ cat garcons arthur pierre jean $

Lorsque le fichier lire est cr par une commande cmd, comme dans le programme wh, on peut utiliser la syntaxe : cmd | while read [ var1 ... ] do commande(s) de traitement de la ligne courante done Exemple : wh1
#!/bin/bash # @(#) wh1

who | while read nom reste do echo $nom done

Par rapport au programme shell wh, il est inutile de grer le fichier temporaire tmp. Exercice : En utilisant la commande ruptime crire un programme shell up qui affiche le nom de toutes les machines qui sont dans l'tat up

58

Exercice : a) b) Ecrire un programme shell etat1 prenant un nom de machine en argument et qui affiche son tat (up ou down). On ne considre aucun cas d'erreur. Modifier ce programme, soit etat2, pour qu'il affiche un message d'erreur lorsque le nom de la machine pass en argument nest pas visible laide de la commande ruptime. Modifier le programme prcdent, soit etat, pour qu'il vrifie galement le nombre d'arguments passs lors del'appel.

c)

Commande interne while et performances La lecture ligne par ligne dun fichier laide dune commande interne while est lente et peu lgante. Il est prfrable dutiliser une suite de filtres permettant daboutir au rsultat voulu. Par exemple, en utilisant un filtre supplmentaire (la commande unix cut), on peut saffranchir de litration while dans le programme wh1. Il suffit dextraire le premier champ de chaque ligne. La commande unix cut permet de slectionner un ou plusieurs champs de chaque ligne dun fichier texte. Un champ peut tre spcifi en prcisant le caractre sparateur de champ (par dfaut, il sagit du caractre tabulation) avec loption d ; les numros de champs doivent alors tre indiqus avec loption -f. Programme wh1.cut ----------------#!/bin/bash # @(#) wh1.cut

who | cut -d ' ' -f1

----------------Ex :
$ wh1.cut sanchis root $

Dans le programme wh1.cut, on prcise que la commande cut doit prendre comme sparateur le caractre espace (-d ' ') et que seul le premier champ de chaque ligne doit tre extrait (-f1). Exercice : Ecrire un programme shell up.cut qui, sans utiliser ditration, affiche le nom de toutes les machines qui sont dans l'tat up.

Une deuxime raison dviter la lecture ligne ligne dun fichier avec while est quelle peut conduire des rsultats diffrents suivant le mode de lecture choisi (tube ou simple redirection).

59

Prenons lexemple o lon souhaite modifier la valeur dune variable var aprs lecture de la premire ligne dun fichier. Le programme shell maj ci-dessous connecte laide dun tube la sortie standard de la commande date lentre de la commande interne while. Aprs lecture de la premire (et unique) ligne, la valeur de la variable var est modifie. Pourtant, cette nouvelle valeur ne sera pas affiche. En effet, lutilisation du tube a pour effet de faire excuter litration while par un processus diffrent : il y a alors deux instances diffrentes de la variable var : celle qui a t initialise 0 au dbut de lexcution de maj et celle interne au nouveau processus qui initialise 1 sa propre instance de var. Aprs terminaison de litration while, le processus qui lexcutait disparat ainsi que sa variable var initialise 1. Programme maj ----------------#!/bin/bash # @(#) var=0 date | while read do var=1 done echo $var maj

----------------Ex :
$ maj 0 $

Lorsque lon excute le programme maj1, bash ne cre pas un nouveau processus pour excuter litration while : il ny a quune instance de la variable var qui est convenablement mise jour. Programme maj1 ----------------#!/bin/bash # @(#) var=0 date > tmp while read do var=1 done < tmp rm tmp echo $var maj1

----------------Ex :
$ maj1 1 $

60

9. Chanes de caractres
9.1. Protection de caractres
Le shell utilise diffrents caractres particuliers pour effectuer ses propres traitements ($ pour la substitution, > pour la redirection de la sortie standard, * comme caractre gnrique, etc.). Pour utiliser ces caractres particuliers comme de simples caractres, il est ncessaire de les protger de l'interprtation du shell. Trois mcanismes sont utilisables : Protection d'un caractre l'aide du caractre \

Ce caractre protge le caractre qui suit immdiatement le caractre \. Ex :


$ echo \* => le caractre * perd sa signification de caractre gnrique * $ echo * tata toto $ $ echo \\ => le deuxime caractre \ perd sa signification de caractre de protection \ $ echo N\'oublie pas ! N'oublie pas ! $

Rq :

dans les exemples de cette section, les caractres en vert ont perdu leur signification particulire, les caractres en rouge sont interprts.

Le caractre \ permet galement dter la signification de la touche Entre. Cela a pour effet daller la ligne sans quil y ait excution de la commande. En effet, aprs saisie dune commande, lutilisateur demande au shell lexcution de celle-ci en appuyant sur cette touche. Annuler linterprtation de la touche Entre autorise lutilisateur crire une longue commande sur plusieurs lignes. Dans lexemple ci-dessous, le shell dtecte que la commande interne echo nest pas termine ; par consquent, bash affiche une chane dappel diffrente matrialise par un caractre > suivi dun caractre espace invitant lutilisateur continuer la saisie de sa commande. Ex :
$ echo coucou \Entre => terminaison de la commande : le shell lexcute ! > salut Entre coucou salut $

Protection de caractres l'aide d'une paire de guillemets "chane"

Tous les caractres de chane sauf $ \ ` " sont protgs de l'interprtation du shell. Cela signifie, par exemple, qu lintrieur dune paire de guillemets le caractre $ sera quand mme interprt comme une substitution, etc. Ex :

$ echo

"< * $PWD

* >"

61

< * /home/sanchis * > $ $ echo "< * \"$PWD\" * > " < * "/home/sanchis" * > $

Protection totale 'chane'

Entre une paire dapostrophes (), aucun caractre de chane (sauf le caractre ') n'est interprt. Ex :
$ echo '< * $PWD < * $PWD * > $ * >'

9.2. Longueur d'une chane de caractres


Syntaxe : ${#paramtre}

Cette syntaxe est remplace par la longueur de la chane de caractres contenue dans paramtre. Ce dernier peut tre une variable, un paramtre spcial ou un paramtre de position. Ex :
$ echo $PWD /home/sanchis $ echo ${#PWD} 14 $ $ set "au revoir" $ echo ${#1} 9 $ $ ls >/dev/null $ $ echo ${#?} 1 $

=> longueur de la chane /home/sanchis

=> la valeur de $1 tant au revoir, sa longueur est 9

=> contenue dans $?, la valeur du code de retour de ls => est 0, par consquent la longueur est 1

9.3. Modificateurs de chanes


Les modificateurs de chanes permettent la suppression d'une sous-chane de caractres correspondant un modle exprim l'aide de caractres ou dexpressions gnriques. Suppression de la plus courte sous-chane gauche Syntaxe : ${paramtre#modle}

62

Ex :

$ echo $PWD /home/sanchis $ $ echo ${PWD#*/} home/sanchis $ $ set "12a34a" $ $ echo ${1#*a} 34a $

=> le premier caractre / a t supprim

=> suppression de la sous-chane 12a

Suppression de la plus longue sous-chane gauche Syntaxe : Ex : ${paramtre##modle}

$ echo $PWD /home/sanchis $ $ echo ${PWD##*/} sanchis => suppression de la plus longue sous-chane gauche se $ => terminant par le caractre / $ set 12a34ab $ $ echo ${1##*a} b $

Suppression de la plus courte sous-chane droite Syntaxe : Ex: ${paramtre%modle}

$ echo $PWD /home/sanchis $ echo ${PWD%/*} /home $

Suppression de la plus longue sous-chane droite Syntaxe : Ex : ${paramtre%%modle}

$ eleve="Pierre Dupont::12:10::15:9" $ $ echo ${eleve%%:*} Pierre Dupont $

La variable eleve contient les prnom, nom et diverses notes d'un lve. Les diffrents champs sont spars par un caractre deux-points. Il peut manquer des notes un lve (cela se caractrise par un champ vide).

63

Exercices : 1. En utilisant les modificateurs de chanes, a) b) crire un programme shell touslesutil qui lit le contenu du fichier /etc/passwd et affiche le nom des utilisateurs enregistrs. modifier ce programme (soit touslesutiluid) pour quil affiche le nom et luid de chaque utilisateur.

2. En utilisant les modificateurs de chanes, a) crire un programme shell basenom ayant un fonctionnement similaire la commande unix basename. Cette commande affiche le dernier lment dun chemin pass en argument. Il n'est pas ncessaire que ce chemin existe rellement. Ex :
$ basename /toto/tata/tutu tutu $

b)

si un suffixe est mentionn comme deuxime argument, celui ci est galement t de l'lment par la commande basename. Ex :
$ basename /toto/tata/tutu/prog.c prog $ .c

Ecrire un programme basenom1 qui se comporte de la mme manire. 3. Ecrire une commande dirnom, similaire la commande unix dirname ; la commande unix dirname peut tre vue comme la commande complmentaire basename car dirname supprime le dernier lment d'un chemin; si cela donne la chane vide, alors le caractre . est affich. Ex :
$ dirname /home/sanchis/bin /home/sanchis $ $ dirname toto $

9.4. Extraction de sous-chanes


${paramtre:ind} : extrait de la valeur de paramtre la sous - chane dbutant l'indice ind. La valeur de paramtre nest pas modifie.

Attention : l'indice du premier caractre d'une chane est 0 64

Ex : ch="abcdefghijk" 01234567..10 ${paramtre:ind:nb} : Ex :

echo ${ch:3} affiche defghijk

extrait nb caractres partir de l'indice ind

$ echo ${ch:8:2} ij $ set ABCDEFGH $ $ echo ${1:4:3} EFG $

Exercice : a) Ecrire un programme calibre prenant deux arguments, une chane de caractres ch et un nombre nb, qui affiche les nb premiers caractres de ch. Aucune erreur ne doit tre traite. b) Modifier le programme prcdent, soit calibre1, pour quil vrifie que : - le nombre darguments est correct - le deuxime argument est un nombre (suite non vide de chiffres).

9.5. Remplacement de sous-chanes


${paramtre/mod/ch} : bash recherche dans la valeur de paramtre la plus longue souschane satisfaisant le modle mod puis remplace cette sous-chane par la chane ch. Seule la premire sous-chane trouve est remplace. La valeur de paramtre nest pas modifie. Caractres et expressions gnriques peuvent tre prsents dans mod. Ce mcanisme de remplacement comprend plusieurs aspects : (1) Remplacement de la premire occurrence Ex :
$ v=totito $ echo ${v/to/lo} lotito $

La valeur de la variable v (totito) contient deux occurrences du modle to. Seule la premire occurrence est remplace par la chane lo. Ex :
$ set topo $ echo $1 topo $ $ echo ${1/o/i} tipo $

(2) Remplacement de la plus longue sous-chane 65

Ex :

$ v=abcfefg $ v1=${v/b*f/toto} $ echo $v1 atotog $

=> utilisation du caractre gnrique *

Deux sous-chanes de v satisfont le modle b*f : bcf et bcfef Cest la plus longue qui est remplace par toto. ${paramtre//mod/ch} : contrairement la syntaxe prcdente, toutes les occurrences (et non seulement la premire) satisfaisant le modle mod sont remplaces par la chane ch

Ex :

$ var=tobatoba $ echo ${var//to/tou} toubatouba $ $ set topo $ echo $1 topo $ $ echo ${1//o/i} tipi $

${paramtre//mod/} : lorsque la chane ch est absente, la premire ou toutes les occurrences (suivant la syntaxe utilise) sont supprimes Ex :
$ v=123azer45ty $ shopt s extglob $ echo ${v//+([[:lower:]])/} 12345 $

Lexpression gnrique +([[:lower:]] dsigne la plus longue suite non vide de minuscules. La syntaxe utilise signifie que toutes les occurrences doivent tre traites : la variable v contient deux occurrences (azer et ty). Le traitement effectuer est la suppression. Il est possible de prciser si lon souhaite loccurrence cherche en dbut de chane de paramtre (syntaxe utiliser : #mod) ou bien en fin de chane (%mod). Ex :
$ v=automoto $ echo ${v/#aut/vel} velomoto $ $ v=automoto $ echo ${v/%to/teur} automoteur $

66

10. Structures de contrle for et if


10.1. Itration for
L'itration for possde plusieurs syntaxes dont les deux plus gnrales sont : Premire forme : for var do suite_de_commandes done Lorsque cette syntaxe est utilise, la variable var prend successivement la valeur de chaque paramtre de position initialis. Exemple : programme for_arg ----------------#!/bin/bash for i do echo $i echo "Passage a l'argument suivant ..." done

----------------Ex :
$ for_arg un deux => deux paramtres de position initialiss un Passage a l'argument suivant ... deux Passage a l'argument suivant ... $

Exercice :

En utilisant la commande ruptime, crire un programme shell etatgene prenant en arguments un ou plusieurs noms de machines et affiche pour chacune delles leur tat (up ou down).

La commande compose for traite les paramtres de position sans tenir compte de la manire dont ils ont t initialiss (lors de lappel dun programme shell ou bien par la commande interne set). Exemple : programme for_set ----------------#!/bin/bash set $(date) for i do echo $i done

-----------------

67

Ex :

$ for_set dimanche 17 dcembre 2006, 11:22:10 (UTC+0100) $

Deuxime forme :

for var in liste_mots do suites_de_commandes done

La variable var prend successivement la valeur de chaque mot de liste_mots. Exemple : programme for_liste --------------------#!/bin/bash for a in toto tata do echo $a done

--------------------Ex :
$ for_liste toto tata $

Si liste_mots contient des substitutions, elles sont pralablement traites par bash. Exemple : programme affich.ls ------------------------#!/bin/bash for i in tmp $(pwd) do echo --- $i --- ls $i done

------------------------Ex :
$ affich.ls --- tmp --gamma --- /home/sanchis/Rep --affich.ls alpha beta tmp $

Exercice :

Ecrire un programme shell lsrep ne prenant aucun argument, qui demande l'utilisateur de saisir une suite de noms de rpertoires et qui affiche leur contenu respectif.

68

10.2. Choix if
La commande interne if implante le choix alternatif. Syntaxe : if suite_de_commandes1 then suite_de_commandes2 [ elif suite_de_commandes ; then suite_de_commandes ] ... [ else suite_de_commandes ] fi

Le fonctionnement est le suivant : suite_de_commandes1 est excute ; si son code de retour est gal 0, alors suite_de_commandes2 est excute sinon c'est la branche elif ou la branche else qui est excute, si elle existe. Exemple : programme rm1 ------------------------------------#!/bin/bash if rm $1 2>/dev/null then echo $1 a ete supprime else echo $1 n\'a pas ete supprime fi

------------------------------------Ex :
$ >toto => cration du fichier toto $ $ rm1 toto toto a ete supprime $ $ rm1 toto toto n'a pas ete supprime $

Lorsque la commande rm1 toto est excute, si le fichier toto est effaable, le fichier est effectivement supprim, la commande unix rm renvoie un code de retour gal 0 et cest la suite de commandes qui suit le mot-cl then qui est excute ; le message toto a ete supprime est affich sur la sortie standard. Si toto nest pas effaable, lexcution de la commande rm choue ; celle-ci affiche un message sur la sortie standard pour les messages derreur que lutilisateur ne voit pas car celle-ci a t redirige vers le puits, puis renvoie un code de retour diffrent de 0. Cest la suite de commandes qui suit else qui est excute : le message toto na pas ete supprime saffiche sur la sortie standard. Les mots if, then, else, elif et fi sont des mots-cl. Par consquent, pour indenter une structure if suivant le style langage C , on pourra lcrire de la manire suivante : if suite_de_commandes1 ; then suite_de_commandes2 else suite_de_commandes ] fi La structure de contrle doit comporter autant de mots-cls fi que de if (une branche elif ne doit pas se terminer par un fi). 69

Ex :

if ... then ... elif ... then ... fi

if ... then ... else if ... then ... fi fi

Dans une succession de if imbriqus o le nombre de else est infrieur au nombre de then, le motcl fi prcise lassociation entre les else et les if. Ex : if ... then ... if ... then ... fi else ... fi

Commande compose [[ La commande interne compose [[ est souvent utilise avec la commande interne compose if. Elle permet lvaluation dexpressions conditionnelles portant sur des objets aussi diffrents que les permissions sur une entre, la valeur dune chane de caractres ou encore ltat dune option de la commande interne set. Syntaxe : [[ expr_cond ]]

Les deux caractres crochets doivent tre colls et un caractre sparateur doit tre prsent de part et dautre de expr_cond. Les mots [[ et ]] sont des mots-cl. Le fonctionnement de cette commande interne est le suivant : lexpression conditionnelle expr_cond est value et si sa valeur est Vrai, alors le code de retour de la commande interne [[ est gal 0. Si sa valeur est Faux, le code de retour est gal 1. Si expr_cond est mal forme ou si les caractres crochets ne sont pas colls, une valeur diffrente est retourne. La commande interne [[ offre de nombreuses expressions conditionnelles ; cest pourquoi, seules les principales formes de expr_cond seront prsentes, regroupes par catgories. . Permissions : -r entre -w entre -x entre vraie si vraie si vraie si entre existe et est accessible en lecture par le processus courant. entre existe et est accessible en criture par le processus courant. le fichier entre existe et est excutable par le processus courant ou si le rpertoire entre existe et le processus courant possde la permission de passage.

70

Ex :

$ echo coucou > toto $ chmod 200 toto $ ls -l toto --w------- 1 sanchis sanchis 7 dc 17 17:21 toto $ $ if [[ -r toto ]] > then cat toto > fi $ => aucun affichage donc toto nexiste pas ou nest pas accessible en lecture, $ => dans le cas prsent, il est non lisible $ $ echo $? 0 => code de retour de la commande interne if $

Mais,
$ [[ -r toto ]] $ $ echo $? => code de retour de la commande interne [[ 1 $

. Types d'une entre : -f entre -d entre Exemple : vraie si vraie si entre existe et est un fichier ordinaire entre existe et est un rpertoire

programme affic ------------------------------------#!/bin/bash if [[ -f $1 ]] then echo $1 : fichier ordinaire cat $1 elif [[ -d $1 ]] then echo $1 : repertoire ls $1 else echo $1 : type non traite fi

------------------------------------. Renseignements divers sur une entre : -a entre -s entre entre1 -nt entre2 entre1 -ot entre2 entre2 vraie si vraie si vraie si rcente vraie si entre existe entre existe et sa taille est diffrente de zro entre1 existe et sa date de modification est plus que celle de entre2 entre1 existe et est plus ancienne que celle de

71

. Longueur dune chane de caractres : -z ch -n ch vraie si vraie si la longueur de la chane ch est gale zro la longueur de la chane ch est diffrente de zro

. Comparaisons de chanes de caractres : ch1 < ch2 ch1 > ch2 vraie si vraie si ch1 prcde ch2 ch1 suit ch2

Lordre des chanes ch1 et ch2 est command par la valeur des paramtres rgionaux. ch == mod ch != mod vraie si vraie si la chane ch correspond au modle mod la chane ch ne correspond pas au modle mod

mod est un modle de chanes pouvant contenir caractres et expressions gnriques. Ex :


$ $ $ $ $ 1 $ $ $ $ 0 $ a="au revoir" [[ $a == 123 ]] echo $?

=> faux

[[ $a == a* ]] echo $?

=> vrai, la valeur de a commence par le caractre a

Si par mgarde ch ou mod ne sont pas dfinies, la commande interne [[ ne provoque pas derreur de syntaxe. Exemple : programme testval ------------------------------------#!/bin/bash if [[ $1 == $a ]] then echo OUI else echo >&2 NON fi

------------------------------------Ex :
$ testval coucou NON $ $ testval OUI $

=> dans testval, $1 est remplac par coucou, la variable a nest pas => dfinie => aucun des deux membres de lgalit nest dfini

72

. Etat dune option : -o opt vraie si ltat de loption opt de la commande interne set est on Ex : $ set -o | grep noglob
noglob off $ $ if [[ -o noglob ]]; then echo ON > else echo OFF > fi OFF $

. Composition d'expressions conditionnelles : ( expr_cond ) ! expr_cond vraie si vraie si expr_cond est vraie. Permet le regroupement dexpressions conditionnelles expr_cond est fausse vraie si les deux expr_cond sont vraies. Lexpression expr_cond2 nest pas value si expr_cond1 est fausse. vraie si une des deux expr_cond est vraie. Lexpression expr_cond2 nest pas value si expr_cond1 est vraie.

expr_cond1 && expr_cond2 expr_cond1 || expr_cond2

Les quatre oprateurs ci-dessus ont t lists par ordre de priorit dcroissante. Ex :
$ ls -l /etc/at.deny -rw-r----- 1 root daemon 144 jan 3 2006 /etc/at.deny $ $ if [[ ! ( -w /etc/at.deny || -r /etc/at.deny ) ]] > then > echo OUI > else > echo NON > fi OUI $

Le fichier /etc/at.deny nest accessible ni en lecture ni en criture pour lutilisateur sanchis ; le code de retour de la commande interne [[ sera gal zro car lexpression conditionnelle est vraie. Attention : on prendra soin de sparer les diffrents oprateurs et symboles par des espaces Ex :
$ if [[ !( -w /etc/at.deny || -r /etc/at.deny ) ]] -bash: !: event : not found $

Dans lexemple ci-dessus, il ny a aucun blanc entre ! et (, ce qui provoque une erreur. En combinant commande interne [[, oprateurs sur les codes de retour et regroupements de commandes, lutilisation dune structure if devient inutile.

73

Ex :

$ [[ -r toto ]] || { > echo >&2 "Probleme de lecture sur toto" > } Probleme de lecture sur toto $

Remarque :

par souci de portabilit, bash intgre galement lancienne commande interne [. Celle-ci possde des fonctionnalits similaires celles de [[ mais est plus dlicate utiliser. Ex :
$ a="au revoir" $ $ [ $a = coucou ] => loprateur galit de [ est le symbole = -bash: [: too many arguments $

Le caractre espace prsent dans la valeur de la variable a provoque une erreur de syntaxe. Il est ncessaire de prendre davantage de prcaution quand on utilise cette commande interne. Ex :
$ [ "$a" = coucou ] $ $ echo $? 1 $

74

11. Entiers et expressions arithmtiques


11.1. Variables de type entier
Pour dfinir et initialiser une ou plusieurs variables de type entier, on utilise la syntaxe suivante : declare -i nom[=expr_arith] [ nom[=expr_arith] ... ] Ex :
$ declare -i x=35 $ $ declare -i v w $ $ v=12 $ $ read w 34 $

=> dfinition et initialisation de la variable entire x => dfinition des variables entires v et w => initialisation de v par affectation => initialisation de w par lecture

Rappel :

Il n'est pas ncessaire de dfinir une variable avant de l'utiliser !

Pour que la valeur dune variable entire ne soit pas accidentellement modifie aprs quelle ait t initialise, il suffit dajouter lattribut r. Ex :
$ declare -ir a=-6 $ $ a=7 -bash: a: readonly variable $

=> seule la consultation est autorise !

Enfin, pour connatre toutes les variables entires dfinies, il suffit dutiliser la commande declare i. Ex :
$ declare -i declare -ir EUID="1007" declare -ir PPID="19620" declare -ir UID="1007" declare -ir a="-6" declare -i v="12" declare -i w="14" declare -i x="35" $

11.2. Commande interne ((


Cette commande interne est utilise pour effectuer des oprations arithmtiques. Syntaxe : (( expr_arith ))

75

Son fonctionnement est le suivant : expr_arith est value ; si cette valuation donne une valeur diffrente de 0, alors le code de retour de la commande interne (( est gal 0 sinon le code de retour est gal 1. Il est donc important de distinguer deux aspects de la commande interne (( expr_arith )) : - la valeur de expr_arith issue de son valuation et - le code de retour de (( expr_arith )). Attention : la valeur de expr_arith n'est pas affiche sur la sortie standard. Ex :
$ $ $ 0 $ $ $ $ 1 $ (( -5 )) echo $?

=> la valeur de l'expression arithmtique est gale -5 (c.--d. => diffrente de 0), donc le code de retour de (( est gal 0

(( 0 )) echo $?

=> la valeur de l'expression arithmtique est 0, donc le code de retour => de (( est gal 1

Les oprateurs permettant de construire des expressions arithmtiques valuables par bash sont issus du langage C (ex : = + - > <=). Ex :
$ declare -i a=2 $ (( b = a + 7 )) $ b

Le format d'criture est libre l'intrieur de la commande ((. En particulier, plusieurs caractres espace ou tabulation peuvent sparer les deux membres d'une affectation. Il est inutile d'utiliser le caractre de substitution $ devant le nom d'une variable car il n'y a pas d'ambigut dans l'interprtation ; par contre, lorsqu'une expression contient des paramtres de position, le caractre $ doit tre utilis. Ex :
$ date jeudi 21 dcembre 2006, 19:41:42 (UTC+0100) $ $ set $(date) $ $ (( b = $2 +1 )) => incrmentation du jour courant $ $ echo $b 22 $

Code de retour de (( et structures de contrle Le code de retour d'une commande interne (( est souvent exploit dans une structure de contrle if ou while.

76

Le programme shell dix ci-dessous affiche les dix chiffres : ------------------------------#!/bin/bash declare -i i=0

while (( i < 10 )) do echo $i (( i = i + 1 )) done

ou (( i++ ))

------------------------------Son fonctionnement est le suivant : lexpression i < 10 est value, sa valeur est vraie, le code de retour de (( i < 10 )) est gal 0, le corps de litration est excut. Aprs affichage de la valeur 9, la valeur devient gale 10. Lexpression i < 10 est value, sa valeur est maintenant fausse, le code de retour de (( i < 10 )) est gal 1, litration se termine. Ex :
$ dix 0 1 2 3 4 5 6 7 8 9 $

11.3. Valeur d'une expression arithmtique


La commande interne (( expr_arith )) n'affiche pas sur la sortie standard la valeur de l'expression arithmtique expr_arith. Pour obtenir la valeur de l'expression arithmtique, on utilise la syntaxe : $(( expr_arith )) Ex :
echo $(( 7 * 2 )) echo $(( a= 12*8 )) echo $(( 7 < 10 ))

Substitutions de commandes et substitutions de paramtres peuvent tre prsentes dans une commande interne (( ou bien dans une substitution dexpression arithmtique $(( )) si le rsultat aboutit un nombre entier. Par exemple, dans lexpression $(( $(ls -l | wc -l) -1 )) le rsultat du pipeline ls -l | wc l peut tre interprt comme un nombre. Attention : Ex : lors de l'valuation d'une expression arithmtique, les dbordements ventuels ne sont pas dtects.
$ echo $((897655*785409*56789*6789999999999999999999 )) -848393034087410691 => nombre ngatif ! $

77

Si lon souhaite utiliser de grands entiers (ou des nombres rels), il est prfrable dutiliser la commande unix bc. Ex :
$ bc q 897655*785409*56789*6789999999999999999999 271856250888322242449959962260546638845 $

Loption q de bc vite laffichage du message de bienvenue lorsquon utilise cette commande de manire interactive. Base sur le contexte, linterprtation des expressions arithmtiques est particulirement souple en bash. Ex :
$ declare -i x=35 $ $ z=x+5 => affectation de la chane x+5 la variable z $ echo $z x+5 => non value car z de type chane de caractres par dfaut $ $ echo $((z)) => par le contexte, z est value comme une variable de type entier 40 $ (( z = z+1)) $ echo $z 41 $

11.4. Oprateurs
Une expression arithmtique contenue dans une commande interne (( peut tre une valeur, un paramtre ou bien tre construite avec un ou plusieurs oprateurs. Ces derniers proviennent du langage C. La syntaxe des oprateurs, leur signification, leur ordre de priorit et les rgles d'associativit sinspirent galement du langage C. Les oprateurs traits par la commande (( sont nombreux. Cest pourquoi, seuls les principaux oprateurs sont mentionns dans le tableau ci-dessous, munis de leur associativit (g : de gauche droite, d : de droite gauche). Ne sont pas prsents dans ce tableau les oprateurs portant sur les reprsentations binaires (ex : et bit bit, ou bit bit, etc.). Les oprateurs ayant mme priorit sont regroups dans une mme classe et les diffrentes classes sont cites par ordre de priorit dcroissante. (1) (2) (3) (4) (5) post-incrmentation, post-dcrmentation pr-incrmentation, pr-dcrmentation moins unaire, plus unaire ngation logique exponentiation : ab (g) (d) (d) (d) (d) 78

a++ ++a -a !a a**b

a---a +a

(6) (7) (8) (9) (10) (11) (12) (13) (14)

a*b a+b a<b

a/b a-b a<=b

a%b

multiplication, division entire, reste addition, soustraction

(g) (g) (g) (g) (g) (g) (d) (d) (g)

a>b a>=b

comparaisons galit, diffrence ET logique OU logique oprateur conditionnel oprateurs d'affectation oprateur virgule

a==b a!=b a&&b a||b a?b:c a=b a*=b a%=b a+=b a-=b a,b

Ces oprateurs se dcomposent en : - oprateurs arithmtiques - oprateurs d'affectations - oprateurs relationnels - oprateurs logiques - oprateurs divers. Oprateurs arithmtiques : Les quatre oprateurs ci-dessous sappliquent une variable. Post-incrmentation : var++ Ex : la valeur de var est dabord utilise, puis est incrmente => y reoit la valeur 9 ; x vaut 10

$ declare -i x=9 y $ (( y = x++ )) $ echo "y=$y x=$x" y=9 x=10 $

Post-dcrmentation : var-Ex :

la valeur de var est dabord utilise, puis est dcrmente => y reoit la valeur 9 ; x vaut 8

$ declare -i x=9 y $ (( y = x-- )) $ echo "y=$y x=$x" y=9 x=8 $

Pr-incrmentation : Ex :

++var

la valeur de var est dabord incrmente, puis est utilise => x vaut 10 ; y reoit la valeur 10

$ declare -i x=9 y $ (( y=++x)) $ echo "y=$y x=$x" y=10 x=10 $

79

Pr-dcrmentation : --var Ex :

la valeur de var est dabord dcrmente, puis est utilise => x vaut 8 ; y reoit la valeur 8

$ declare -i x=9 y $ (( y= --x )) $ echo "y=$y x=$x" y=8 x=8 $

Les autres oprateurs sappliquent des expressions arithmtiques. Moins unaire : Addition : Soustraction : Multiplication : Division entire : Reste de division entire : Ex : - expr_arith expr_arith + expr_arith expr_arith - expr_arith expr_arith * expr_arith expr_arith / expr_arith expr_arith % expr_arith => division entire et addition => reste et addition

$ (( a = b/3 +c )) $ $ echo $(( RANDOM%49 +1 )) 23 $

La variable prdfinie du shell RANDOM renvoie une valeur pseudo-alatoire ds qu'elle est utilise. L'utilisation de parenthses permet de modifier l'ordre d'valuation des composantes d'une expression arithmtique. Ex :
$ (( a = ( b+c )*2 )) $

Oprateurs d'affectations : Affectation simple : Affectation compose : nom = expr_arith nom oprateur=

expr_arith

Comme en langage C, l'affectation n'est pas une instruction (on dirait commande dans la terminologie du shell) mais une expression, et comme toute expression elle possde une valeur. Celle-ci est la valeur de son membre gauche aprs valuation de son membre droit. Ex :
$ ((a=b=c=5)) $ echo $a $b $c 5 5 5 $

=> la valeur de lexpression a=b=c=5 est gale 5

Dans l'exemple ci-dessous, l'expression a = b + 5 est value de la manire suivante : b est value (sa valeur est 2), puis c'est l'expression b+5 qui est value (sa valeur vaut 7), enfin cette valeur est affecte la variable a. La valeur de l'expression a = b + 5 est gale celle de a, c'est dire 7. Ceci permet d'crire : 80

Ex :

$ declare i b=2 $ $ echo $(( a = b+5 )) 7 $ $ echo $a 7 $

La syntaxe nom signifiant :

oprateur=

expr_arith est un raccourci d'criture provenant du langage C et

nom = nom oprateur expr_arith oprateur pourra tre : Ex :


$ (( a += 1 )) $

* / + => ceci est quivalent (( a = a + 1 ))

Oprateurs relationnels : Lorsqu'une expression relationnelle (ex : a < 3) est vraie, la valeur de l'expression est gale 1. Lorsqu'elle est fausse, sa valeur est gale 0. Egalit : Diffrence : Infrieur ou gal : Suprieur ou gal : Strictement infrieur : Strictement suprieur : Ex :
$ declare i $ $ (( a<3 )) $ echo $? 1 $ $ declare $ $ if (( a > then (( > else (( > fi $ $ echo $a 14 $ a=4

expr_arith expr_arith expr_arith expr_arith expr_arith expr_arith

== != <= >= < >

expr_arith expr_arith expr_arith expr_arith expr_arith expr_arith

(Attention aux deux caractres gal)

=> expression fausse, valeur gale 0, code de retour gal 1

Ex :

i a=3 b=2 == 7 )) a= 2*b )) a = 7*b))

L'expression relationnelle a == 7 est fausse, sa valeur est 0 et le code de retour de (( a == 7 )) est gal 1: c'est donc la partie else qui est excute.

81

Oprateurs logiques : Comme pour une expression relationnelle, lorsqu'une expression logique (ex : a > 3 && a < 5) est vraie, la valeur de l'expression est gale 1. Lorsqu'elle est fausse, sa valeur est gale 0. Ngation logique : ! expr_arith

Si la valeur de expr_arith est diffrente de 0, la valeur de ! expr_arith est gale 0. Si la valeur de expr_arith est gale 0, la valeur de ! expr_arith est gale 1. Au moins un caractre espace doit tre prsent entre ! et expr_arith. Ex :
$ echo $(( ! 12 )) 0 $

=> echo $(( !12 ))

provoque une erreur

Et logique :

expr_arith1 && expr_arith2

Si la valeur de expr_arith1 est gale 0 (fausse), alors expr_arith2 n'est pas value et la valeur de expr_arith1 && expr_arith2 est 0. Si la valeur de expr_arith1 est diffrente de 0 (vraie), alors expr_arith2 est value : si sa valeur est gale 0, alors la valeur de expr_arith1 && expr_arith2 est 0, sinon elle vaut 1. Ex:
$ $ $ 0 $ $ 1 $ $ 0 $ declare i a=4 echo $(( a<3 ))

=> expression fausse


a <5 ))

echo $(( a > 3 &&

=> expression vraie, valeur gale 1

((a>3 && a<5 )) => expression vraie, code de retour gal 0 echo $?

Ou logique :

expr_arith1 || expr_arith2

Si la valeur de expr_arith1 est diffrente de 0 (vraie), alors expr_arith2 n'est pas value et la valeur de expr_arith1 || expr_arith2 est gale 1. Si la valeur de expr_arith1 est gale 0 (fausse), alors expr_arith2 est value : si sa valeur est diffrente de 0, alors la valeur de expr_arith1 || expr_arith2 est 1, sinon elle vaut 0. Ex :
$ $ $ $ 1 $ $ 0 $ declare i x=4 (( x > 4 || x < 4 )) echo $? echo $(( x > 4 || x<4 ))

82

Oprateurs divers : Exponentiation : expr_arith1 ** expr_arith2

Contrairement aux autres oprateurs, loprateur dexponentiation ** nest pas issu du langage C. A partir de la version 3.1 de bash, son associativit a chang : elle est de droite gauche (d). Ex :
$ echo $(( 2**3**2 ) 512 $

=> interprte comme 2**(3**2) : 29

Oprateur conditionnel :

expr_arith1 ? expr_arith2 : expr_arith3

Le fonctionnement de cet oprateur ternaire est le suivant : expr_arith1 est value, si sa valeur est vraie la valeur de l'expression arithmtique est celle de expr_arith2, sinon c'est celle de expr_arith3. Ex :
$ declare -i a=4 b=0 $ echo $(( a < 3 ? (b=5) : (b=54) )) 54 $ $ echo $b 54 $

Il aurait galement t possible dcrire : (( b = a < 3 ? 5 : 54 )) Oprateur virgule : expr_arith1 , expr_arith2

expr_arith1 est value, puis expr_arith2 est value ; la valeur de lexpression est celle de expr_arith2. Ex :
$ declare -i a b $ echo $(( a=4,b=9 )) 9 $ echo "a=$a b=$b" a=4 b=9 $

11.5. Structure for pour les expressions arithmtiques


Bash a introduit une nouvelle structure for adapte aux traitements des expressions arithmtiques, itration issue du langage C. Elle fonctionne comme cette dernire. Syntaxe : for (( expr_arith1 ; expr_arith2 ; expr_arith3 )) do suite_cmd done

83

expr_arith1 est l'expression arithmtique d'initialisation. expr_arith2 est la condition darrt de litration. expr_arith3 est lexpression arithmtique qui fixe le pas dincrmentation ou de dcrmentation. Exemples :

declare -i x for (( x=0 ; x<5 ; x++ )) do echo $(( x*2 )) done

declare -i x y for (( x=1,y=10 ; x<4 ; x++,y-- )) do echo $(( x*y )) done

Exercice :

En utilisant RANDOM, crire un programme tirage_flash qui affiche six entiers diffrents compris entre 1 et 49. Ecrire un programme factiter qui prend un entier N positif ou nul en argument et affiche sa factorielle N! Attention aux dbordements : N ne doit pas tre trop grand. Ex :
$ factiter 7 5040 $ $ factiter 0 1 $

Exercice :

Exercice :

Ecrire une version rcursive factrecur du programme prcedent.

11.6. Exemple : les tours de Hanoi


Le problme des tours de Hano peut snoncer de la manire suivante : - conditions de dpart : plusieurs disques sont placs sur une table A, les uns sur les autres, rangs par taille dcroissante, le plus petit tant au dessus de la pile - rsultat attendu : dplacer cette pile de disques de la table A vers une table B - rgles de fonctionnement : . on dispose d'une troisime table C, . on ne peut dplacer qu'un disque la fois, celui qui est plac en haut d'une pile et le dposer uniquement sur un disque plus grand que lui ou bien sur une table vide. Le programme shell rcursif hanoi traite ce problme ; il utilise quatre arguments : le nombre de disques et le nom de trois tables.

84

hanoi ---------------------------------------#!/bin/bash if (( $1 > 0 )) then hanoi $(( $1 - 1)) $2 $4 $3 echo Deplacer le disque de la table $2 a la table $3 hanoi $(( $1 - 1)) $4 $3 $2 fi

---------------------------------------Pour excuter ce programme, on indique le nombre total N de disques prsents sur la premire table, le nom de la table o sont placs ces N disques et le nom des deux autres tables. Dans l'exemple mentionn, la table A contient au dpart trois disques et les deux autres tables B et C sont vides. Le programme affiche chaque dplacement effectu. Ex :
$ hanoi 3 A Deplacer le Deplacer le Deplacer le Deplacer le Deplacer le Deplacer le Deplacer le $ B C disque disque disque disque disque disque disque de de de de de de de la la la la la la la table table table table table table table A A B A C C A a a a a a a a la la la la la la la table table table table table table table B C C B A B B

85

12. Tableaux
Moins utiliss que les chanes de caractres ou les entiers, bash intgre galement les tableaux monodimensionnels.

12.1. Dfinition et initialisation dun tableau


Pour crer un tableau, on utilise gnralement l'option -a (comme array) de la commande interne declare : declare -a nomtab ...

Le tableau nomtab est simplement cr mais ne contient aucune valeur : le tableau est dfini mais n'est pas initialis. Pour connatre les tableaux dfinis : Ex : declare -a

$ declare -a declare -a BASH_ARGC='()' declare -a BASH_ARGV='()' declare -a BASH_LINENO='()' declare -a BASH_SOURCE='()' declare -ar BASH_VERSINFO='([0]="3" [4]="release" [5]="i486-pc-linux-gnu")' declare -a DIRSTACK='()' declare -a FUNCNAME='()' declare -a GROUPS='()' declare -a PIPESTATUS='([0]="0")' $

[1]="1"

[2]="17"

[3]="1"

Pour dfinir et initialiser un tableau :

declare -a nomtab=( val0 val1 ... )

Comme en langage C, l'indice d'un tableau dbute toujours 0 et sa valeur maximale est celle du plus grand entier positif reprsentable dans ce langage (bash a t crit en C). L'indice peut tre une expression arithmtique. Pour dsigner un lment d'un tableau, on utilise la syntaxe : Ex :
$ declare -a tab => dfinition du tableau tab $ $ read tab[1] tab[3] coucou bonjour $ $ tab[0]=hello $

nomtab[indice]

Il n'est pas obligatoire dutiliser la commande interne declare pour crer un tableau, il suffit d'initialiser un de ses lments : Ex :
$ array[3]=bonsoir $

=> cration du tableau array avec => initialisation de llment dindice 3 86

Trois autres syntaxes sont galement utilisables pour initialiser globalement un tableau : nomtab=( val0 val1 ... ) nomtab=( [indice]=val ... ) Ex : $ arr=([1]=coucou $ [3]=hello)

l'option -a de la commande interne read ou readonly : Ex :


$ read -a tabmess bonjour tout le monde $

12.2. Valeur d'un lment d'un tableau


On obtient la valeur d'un lment d'un tableau laide la syntaxe : ${nomtab[indice]} bash calcule d'abord la valeur de l'indice puis l'lment du tableau est remplac par sa valeur. Il est possible d'utiliser toute expression arithmtique valide de la commande interne (( pour calculer l'indice d'un lment. Ex :
$ echo ${tabmess[1]} tout $ $ echo ${tabmess[RANDOM%4]} monde $ $ echo ${tabmess[1**2+1]} le $

# ou bien ${tabmess[$((RANDOM%4))]}

Pour obtenir la longueur d'un lment d'un tableau : ${#nomtab[indice]} Ex :


$ echo ${tabmess[0]} bonjour $ $ echo ${#tabmess[0]} 7 $

=> longueur de la chane bonjour

Lorsqu'un tableau sans indice est prsent dans une chane de caractres ou une expression, bash utilise l'lment d'indice 0. Ex :
$ echo $tabmess bonjour $

Rciproquement, une variable non pralablement dfinie comme tableau peut tre interprte comme un tableau. 87

Ex :

$ var=bonjour => var est interprte comme un tableau un seul lment $ echo ${var[0]} bonjour => dindice 0 $ var=( coucou ${var[0]} ) => var est devenu un vritable tableau $ echo ${var[1]} bonjour $

Exercice :

Ecrire un programme shell carte qui affiche le nom d'une carte tire au hasard d'un jeu de 32 cartes. On utilisera deux tableaux : un tableau couleur et un tableau valeur. Ex :
$ carte huit de carreau $ carte as de pique $

12.3. Caractristiques d'un tableau


Le nombre d'lments d'un tableau est dsign par : Seuls les lments initialiss sont compts. Ex :
$ echo ${#arr[*]} 2 $

${#nomtab[*]}

Tous les lments d'un tableau sont accessibles laide de la notation : ${nomtab[*]} Seuls les lments initialiss sont affichs. Ex :
$ echo ${arr[*]} coucou hello $

Pour obtenir la liste de tous les indices conduisant un lment dfini dun tableau, on utilise la syntaxe : ${ !nomtab[*]} Ex :
$ arr=([1]=coucou bonjour [5]=hello) $ $ echo ${!arr[*]} 1 2 5 $

Lintrt dutiliser cette syntaxe est quelle permet de ne traiter que les lments dfinis dun tableau trous . Ex :
$ > > > 1 2 5 $ for i in ${!arr[*]} do echo "$i => ${arr[i]}" done => coucou => bonjour => hello

=> dans lexpression ${arr[i]}, bash interprte => directement i comme un entier

88

Pour ajouter un lment val un tableau tab : - la fin : tab[${#tab[*]}]=val - en tte : tab=( val ${tab[*]} ) Ex :
$ tab=( un deux trois ) $ echo ${#tab[*]} 3 $ tab[${#tab[*]}]=fin $ echo ${tab[*]} un deux trois fin $ tab=( debut ${tab[*]} ) $ echo ${tab[*]} debut un deux trois fin $

=> =>

ajout en fin de tableau ajout en tte de tableau

Exercice :

Ecrire un programme shell distrib qui cre un paquet de 5 cartes diffrentes tires au hasard parmi un jeu de 32 cartes et affiche le contenu du paquet. Ecrire un programme shell tabnoms qui place dans un tableau les noms de tous les utilisateurs enregistrs dans le systme, affiche le nombre total d'utilisateurs enregistrs, puis tire au hasard un nom d'utilisateur.

Exercice :

Si lon souhaite crer un tableau dentiers on utilise la commande declare ai. Lordre des options na aucune importance. Ex :
$ declare ai tabent=( 2 45 -2 ) $

Pour crer un tableau en lecture seule, on utilise les options ra : Ex :


$ declare -ra tabconst=( bonjour coucou salut ) => tableau en lecture seule $ $ tabconst[1]=ciao -bash: tabconst: readonly variable $ $ declare -air tabInt=( 34 56 ) => tableau (dentiers) en lecture seule $ echo $(( tabInt[1] +10 )) 66 $ (( tabInt[1] += 10 )) -bash: tabInt: readonly variable $

12.4. Suppression d'un tableau


Pour supprimer un tableau ou lment d'un tableau, on utilise la commande interne unset. Suppression d'un tableau : unset nomtab ... Suppression d'un lment d'un tableau : unset nomtab[indice] ... 89

13. Alias
Un alias permet d'abrger une longue commande, de remplacer le nom dune commande existante par un autre nom ou bien de modifier le comportement dune commande existante.

13.1. Cration dun alias


Pour crer un ou plusieurs alias, on utilise la syntaxe : Ex :
$ alias $ cx=chmod u+x

alias nom=valeur ...

Le nom de lalias peut tre prsent dans sa propre dfinition. La commande alias rm='rm -i' redfinit le comportement par dfaut de la commande unix rm en demandant lutilisateur de confirmer la suppression (on force lutilisateur utiliser loption -i). Ex :
$ alias rm='rm -i' $ => cration du fichier err $ > err $ $ rm err rm: dtruire fichier rgulier vide `err'? o => lalias rm demande $ => confirmation $ ls err ls: err: Aucun fichier ou rpertoire de ce type => le fichier err a t => supprim $

Attention : on ne doit pas dfinir un alias et utiliser cet alias dans la mme ligne mais sur deux lignes diffrentes. Ex :
$ alias aff='echo bonjour' ; aff tout le monde -bash: aff: command not found => aff tout le monde na pu sexcuter ! $ $ aff la compagnie bonjour la compagnie => lalias est connu $

Si l'on dsire utiliser plusieurs alias dans la mme commande, il est ncessaire de laisser un caractre espace ou tabulation comme dernier caractre de valeur. Ex :
$ cat /etc/debian_version 4.0 $ $ alias c=cat d=/etc/debian_version $ $ c d cat: d: Aucun fichier ou rpertoire de ce type $

90

Dans lexemple ci-dessus, lalias d na pas t interprt car le dernier caractre de la valeur de c nest ni un espace, ni une tabulation. En ajoutant un caractre espace, on obtient le rsultat voulu. Ex :
$ alias c='cat ' $ $ c d 4.0 $

La valeur dun alias peut inclure plusieurs commandes. Ex :


$ pwd /tmp => rpertoire courant $ alias scd='echo salut ; cd ' => aprs cd il y a un caractre espace $ alias rep=/home/sanchis/bin $ $ scd rep salut $ pwd => nouveau rpertoire courant /home/sanchis/bin $

La protection de la valeur dun alias doit tre choisie judicieusement. Dfinissons un alias affichant lheure courante. La suite de commandes excuter est la suivante : set $(date) ; echo ${5%:*} Cette suite de commandes peut tre entoure avec des caractres quote ou bien avec des caractres guillemet. Ex :
$ date vendredi 22 dcembre 2006, 18:45:38 (UTC+0100) $ $ alias h='set $(date) ; echo ${5%:*}' $ $ h 18:46 $ $ sleep 60 ... => attente de 60 secondes $ h => mise jour de lheure 18:47 $

Attention : en entourant la suite de commandes avec des caractres guillemet, le shell excute les substitutions avant daffecter la valeur lalias, puis interprte cet alias. Ex :
$ alias g="set $(date) ; echo ${5%:*}" $ $ g -bash: syntax error near unexpected token `(' $

91

Cest la prsence de la parenthse ouvrante de la chane de caractres set vendredi 22 dcembre 2006, 19:08:21 (UTC+0100) Cette chane est excute comme une commande par le shell, ce qui provoque lerreur. Liste des alias dfinis : Pour connatre lensemble des alias dfinis, on utilise la commande alias sans argument : Ex :
$ alias alias aff='echo bonjour' alias c='cat ' alias cx='chmod u+x' alias d='/etc/debian_version' alias g='set vendredi 22 dcembre 2006, 19:08:21 (UTC+0100) ; echo ' alias h='set $(date) ; echo ${5%:*}' alias ll='ls -l' alias ls='ls --color=auto' alias rep='/home/sanchis/bin' alias rm='rm -i' alias scd='echo salut ; cd ' $

Pour connatre la valeur dun ou plusieurs alias : Ex :


$ alias ll alias ll='ls -l' $

alias nom

13.2. Suppression dun alias


Pour rendre indfinie la valeur dun ou plusieurs alias, on utilise la commande unalias. La syntaxe est : Ex : unalias nom ...

$ unalias g rep aff scd $ $ alias alias c='cat ' alias cx='chmod u+x' alias d='/etc/debian_version' alias h='set $(date) ; echo ${5%:*}' alias ll='ls -l' alias ls='ls --color=auto' alias rm='rm -i' $

92

14. Fonctions shell


14.1. Dfinition dune fonction
Le shell bash propose plusieurs syntaxes pour dfinir une fonction. Nous utiliserons celle-ci : function nom_fct { suite_de_commandes } nom_fct spcifie le nom de la fonction. Le corps de celle-ci est suite_de _commandes. Pour appeler une fonction, il suffit de mentionner son nom. Comme pour les autres commandes composes de bash, une fonction peut tre dfinie directement partir dun shell interactif. Ex :
$ function f0 > { > echo Bonjour tout le monde ! > } $ $ f0 => appel de la fonction f0 Bonjour tout le monde ! $

Les mots rservs function et } doivent tre les premiers mots d'une commande pour quils soient reconnus. Sinon, il suffit de placer un caractre point-virgule avant le mot-cl : function nom { suite_de_commandes ;} La dfinition dune fonction la C est galement possible : function nom { suite_de_commandes } L'excution d'une fonction s'effectue dans l'environnement courant, autorisant ainsi le partage de variables. Ex :
$ c=Coucou $ $ function f1 > { => utilisation dans la fonction dune variable externe c > echo $c > } $ $ f1 Coucou $

93

Les noms de toutes les fonctions dfinies peuvent tre lists l'aide de la commande : declare -F Ex :
$ declare -F declare -f f0 declare -f f1 $

Les noms et corps de toutes les fonctions dfinies sont affichs laide de la commande : declare -f Ex :
$ declare -f f0 () { echo Bonjour tout le monde ! } f1 () { echo $c } $

Pour afficher le nom et corps dune ou plusieurs fonctions : declare -f nomfct ... Ex :
$ declare -f f0 f0 () { echo Bonjour tout le monde ! } $

Une dfinition de fonction peut se trouver en tout point dun programme shell ; il nest pas obligatoire de dfinir toutes les fonctions en dbut de programme. Il est uniquement ncessaire que la dfinition dune fonction soit faite avant son appel effectif, c'est--dire avant son excution : function f1 { ... ;} suite_commandes1 function f2 { ... ;} suite_commandes2 Dans le code ci-dessus, suite_commandes1 ne peut excuter la fonction f2 (contrairement suite_commandes2). Cela est illustr par le programme shell appelAvantDef :

94

appelAvantDef
----------------------------------# !/bin/bash echo Appel Avant definition de fct fct function fct { echo Execution de : fct sleep 2 echo Fin Execution de : fct } echo Appel Apres definition de fct fct - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - # fct definie # fct non definie

Son excution se droule de la manire suivante : Ex :


$ appelAvantDef Appel Avant definition de fct ./appelAvantDef: line 4: fct: command not found Appel Apres definition de fct Execution de : fct Fin Execution de : fct $

Lors du premier appel la fonction fct, celle-ci nest pas dfinie : une erreur dexcution se produit. Puis, le shell lit la dfinition de la fonction fct : le deuxime appel seffectue correctement. Contrairement au programme prcdent, dans le programme shell pingpong, les deux fonctions ping et pong sont dfinies avant leur appel effectif : pingpong
- - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - #!/bin/bash function ping { echo ping if (( i > 0 )) then ((i--)) pong fi } function pong { echo pong if (( i > 0 )) then ((i--)) ping fi } declare -i i=4 ping # (1) ping et pong sont definies - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - -

95

Au point (1), les corps des fonctions ping et pong ont t lus par linterprteur de commandes bash : ping et pong sont dfinies.
Ex :
$ pingpong ping pong ping pong ping $

14.2. Suppression dune fonction


Une fonction est rendue indfinie par la commande interne : Ex :
$ declare -F declare -f f0 declare -f f1 $ $ unset -f f1

unset -f nomfct ...

$ $ declare -F $

declare -f f0

=> la fonction f1 nexiste plus !

14.3. Trace des appels aux fonctions


Le tableau prdfini FUNCNAME contient le nom des fonctions en cours dexcution, matrialisant la pile des appels. Le programme shell traceAppels affiche le contenu de ce tableau au dbut de son excution, c'est-dire hors de toute fonction : le contenu du tableau FUNCNAME est vide (a). Puis la fonction f1 est appele, FUNCNAME contient les noms f1 et main (b). La fonction f2 est appele par f1 : les valeurs du tableau sont f2, f1 et main (c). Lorsque lon est lintrieur dune fonction, la syntaxe $FUNCNAME (ou ${FUNCNAME[0]}) renvoie le nom de la fonction courante. traceAppels
- - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - #!/bin/bash function f2 { echo " ------ Dans f2 :" echo " ------ FUNCNAME : $FUNCNAME" echo " ------ tableau FUNCNAME[] : ${FUNCNAME[*]}" }

96

function f1 { echo " --- Dans f1 :" echo " --- FUNCNAME : $FUNCNAME" echo " --- tableau FUNCNAME[] : ${FUNCNAME[*]}" echo " --- - Appel a f2 " echo f2 } echo "Debut :" echo "FUNCNAME : $FUNCNAME" echo "tableau FUNCNAME[] : ${FUNCNAME[*]}" echo f1 - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - -

Ex :

$ traceAppels Debut : FUNCNAME : tableau FUNCNAME[] : --------Dans f1 : FUNCNAME : f1 tableau FUNCNAME[] : f1 main - Appel a f2

(a)

(b)

------ Dans f2 : ------ FUNCNAME : f2 ------ tableau FUNCNAME[] : f2 f1 main $

(c)

14.4. Arguments dune fonction


Les arguments dune fonction sont rfrencs dans son corps de la mme manire que les arguments dun programme shell le sont : $1 rfrence le premier argument, $2 le deuxime, etc., $# le nombre darguments passs lors de lappel de la fonction. Le paramtre spcial $0 nest pas modifi : il contient le nom du programme shell. Pour viter toute confusion avec les paramtres de position qui seraient ventuellement initialiss dans le code appelant la fonction, la valeur de ces derniers est sauvegarde avant lappel la fonction puis restitue aprs excution de la fonction. Le programme shell args illustre ce mcanisme de sauvegarde/restitution : args
- - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - #!/bin/bash function f { echo " --- Dans f : \$0 : $0" echo " --- Dans f : \$# : $#" echo " --- Dans f : \$1 : $1" }

=> affichage du 1er argument de la fonction f

97

echo "Avant f : \$0 : $0" echo "Avant f : \$# : $#" echo "Avant f : \$1 : $1" => affichage du 1er argument du programme args f pierre paul jacques => affichage du 1er argument du programme args echo "Apres f : \$1 : $1" - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - -

Ex :

$ args un deux trois quatre Avant f : $0 : ./args Avant f : $# : 4 Avant f : $1 : un --- Dans f : $0 : ./args --- Dans f : $# : 3 --- Dans f : $1 : pierre Apres f : $1 : un $

Utilise dans le corps dune fonction, la commande interne shift dcale la numrotation des paramtres de position internes la fonction. argsShift
----------------------------------#!/bin/bash function f { echo " --- Dans f : Avant 'shift 2' : \$* : $*" shift 2 echo " --- Dans f : Apres 'shift 2' : \$* : $*" } echo Appel : f un deux trois quatre f un deux trois quatre -----------------------------------

Ex :

$ argsShift Appel : f un deux trois quatre --- Dans f : Avant 'shift 2' : $* : un deux trois quatre --- Dans f : Apres 'shift 2' : $* : trois quatre $

Quelle soit utilise dans une fonction ou lextrieur de celle-ci, la commande interne set modifie toujours la valeur des paramtres de position. argsSet
----------------------------------#!/bin/bash function f { echo " -- Dans f : Avant execution de set \$(date) : \$* : $*" set $(date) cho " -- Dans f : Apres execution de set \$(date) : \$* : $*" } echo Appel : f alpha beta f alpha beta -----------------------------------

98

Ex :

$ argsSet
Appel : f alpha beta -- Dans f : Avant execution de set $(date) : $* : alpha beta -- Dans f : Apres execution de set $(date) : $* : mar mar 7 18:41:39 CET 2006

14.5. Variables locales une fonction


Par dfaut, une variable dfinie lintrieur dune fonction est globale ; cela signifie quelle est directement modifiable par les autres fonctions du programme shell. Dans le programme shell glob, la fonction fUn est appele en premier. Celle-ci cre et initialise la variable var. Puis la fonction fDeux est appele et modifie la variable (globale) var. Enfin, cette variable est nouveau modifie puis sa valeur est affiche. glob
----------------------------------#!/bin/bash function fUn { var=Un # creation de la variable var

}
function fDeux var=${var}Deux } fUn fDeux var=${var}Princ

# premiere modification de var

# deuxieme modification de var

echo $var -----------------------------------

Ex :

$ glob UnDeuxPrinc $

=> trace des modifications successives de la variable globale var

Pour dfinir une variable locale une fonction, on utilise la commande interne local. Sa syntaxe est : local [option] [nom[=valeur] ...] Les options utilisables avec local sont celles de la commande interne declare. Par consquent, on dfinira une ou plusieurs variables de type entier avec la syntaxe local i (local a pour un tableau local). Le programme shell loc dfinit une variable entire a locale la fonction f1. Cette variable nest pas accessible lextrieur de cette fonction.

99

loc
----------------------------------#!/bin/bash function f1 { local -i a=12 (( a++ )) echo "-- Dans f1 : a => $a" } f1 echo "Dans main : a => $a" -----------------------------------

=> a est une variable locale f1

=> tentative daccs la valeur de a

Ex :

$ loc -- Dans f1 : a => 13 Dans main : a => $

=> a nest pas visible dans le corps du programme

La porte d'une variable locale inclut la fonction qui l'a dfinie ainsi que les fonctions qu'elle appelle (directement ou indirectement). Dans le programme shell appelsCascade, la variable locale x est vue : - dans la fonction f1 qui dfinit cette variable - dans la fonction f2 qui est appele par la fonction f1 - dans la fonction f3 qui est appele par la fonction f2. appelsCascade
----------------------------------#!/bin/bash function f3 { (( x = -x )) echo "f3 : x=$x" } function f2 { echo "f2 : $((x+10))" f3 } function f1 { local -i x x=2 f2 echo "f1 : x=$x" }

=> modification de x dfinie dans la fonction f1

=> utilisation de x dfinie dans la fonction f1 => appel de f3

=> initialisation de x => appel de f2

f1 => appel de f1 -----------------------------------

100

Ex :

$ appelsCascade 2 : 12 f3 : x=-2 f1 : x=-2 $

14.6. Exporter une fonction


Pour quune fonction puisse tre excute par un programme shell diffrent de celui o elle a t dfinie, il est ncessaire dexporter cette fonction. On utilise la commande interne export. Syntaxe : export -f nomfct ...

Pour que lexport fonctionne, le sous-shell qui excute la fonction doit avoir une relation de descendance avec le programme shell qui exporte la fonction. Le programme shell progBonj dfinit et utilise une fonction bonj. Ce script lance lexcution dun programme shell autreProgShell qui utilise galement la fonction bonj (mais qui ne la dfinit pas) ; autreProgShell tant excut dans un environnement diffrent de progBonj, il ne pourra trouver la dfinition de la fonction bonj : une erreur dexcution se produit. progBonj
- - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - #!/bin/bash function bonj { echo bonj : Bonjour $1 } bonj Madame autreProgShell - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - -

autreProgShell
- - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - #!/bin/bash echo appel a la fonction externe : bonj bonj Monsieur - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - -

Ex:

$ progBonj bonj : Bonjour Madame appel a la fonction externe : bonj ./autreProgShell: line 4: bonj: command not found $

101

Pour que la fonction bonj puisse tre excute par autreProgShell, il suffit que le programme shell qui la contient exporte sa dfinition. progBonjExport
- - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - #!/bin/bash function bonj { echo bonj : Bonjour $1 } export -f bonj bonj Madame autreProgShell -----------------------------------

=> la fonction bonj est exporte

Aprs son export, la fonction bonj sera connue dans les sous-shells crs lors de lexcution de progBonjExport. Ex :
$ progBonjExport bonj : Bonjour Madame appel a la fonction externe : bonj => affich lors de lexcution de autreProgShell bonj : Bonjour Monsieur $

La visibilit dune fonction exporte est similaire celle dune variable locale, c'est--dire une visibilit arborescente dont la racine est le point dexport de la fonction. Le programme shell progBonjExport2Niv dfinit et exporte la fonction bonj. Celle-ci est utilise dans le programme shell autreProg1 excut par progBonjExport2Niv et est utilise par le programme shell autreProg2 excut par autreProg1. progBonjExport2Niv
----------------------------------#!/bin/bash function bonj { echo bonj : Bonjour $1 } export -f bonj bonj Madame autreProg1 -----------------------------------

102

autreProg1
----------------------------------#!/bin/bash echo "$0 : appel a la fonction externe : bonj" bonj Monsieur autreProg2 -----------------------------------

autreProg2
----------------------------------#!/bin/bash echo "$0 : appel a la fonction externe : bonj" bonj Mademoiselle -----------------------------------

Ex :

$ progBonjExport2Niv bonj : Bonjour Madame ./autreProg1 : appel a la fonction externe : bonj bonj : Bonjour Monsieur ./autreProg2 : appel a la fonction externe : bonj bonj : Bonjour Mademoiselle $

14.7. Commande interne return


Syntaxe : return [ n ]

La commande interne return permet de sortir dune fonction avec comme code de retour la valeur n (0 255). Celle-ci est mmorise dans le paramtre spcial ?. Si n n'est pas prcis, le code de retour fourni est celui de la dernire commande excute. Dans le programme shell return0, la fonction f retourne le code de retour 1 au corps du programme shell. retour0
----------------------------------#!/bin/bash function f { echo coucou return 1 echo a demain }

# jamais execute

f echo code de retour de f : $? -----------------------------------

Ex :

$ return0 coucou code de retour de f : 1 $

103

Remarque :

il ne faut confondre return et exit. Cette dernire arrte lexcution du programme shell qui la contient.

14.8. Substitution de fonction


La commande interne return ne peut retourner quun code de retour. Pour rcuprer la valeur modifie par une fonction, on peut : - enregistrer la nouvelle valeur dans une variable globale, ou - faire crire la valeur modifie sur la sortie standard, ce qui permet la fonction ou programme appelant de capter cette valeur grce une substitution de fonction : $( fct [ arg ] ).

recupres
----------------------------------#!/bin/bash function ajouteCoucou { echo $1 coucou } echo la chaine est : $( ajouteCoucou ----------------------------------bonjour )

La fonction ajouteCoucou prend un argument et lui concatne la chane coucou. La chane rsultante est crite sur la sortie standard afin dtre rcupre par lappelant. Ex :
$ recupres La chaine est: bonjour coucou $

14.9. Fonctions rcursives


Comme pour les programmes shell, bash permet lcriture de fonctions rcursives. Le programme fctfactr implante le calcul dune factorielle sous la forme dune fonction shell f rcursive. Outre la rcursivit, ce programme illustre - la dfinition dune fonction au milieu dun programme shell - la substitution de fonction. fctfactr
----------------------------------#!/bin/bash shopt -s extglob if (( $# != 1 )) || [[ $1 != +([0-9]) ]] then echo "syntaxe : fctfactr n" >&2 exit 1 fi

104

function f { declare -i n if (( $1 == 0 )) then echo 1 else (( n=$1-1 )) n=$( f $n ) echo $(( $1 * $n )) fi } f $1 -----------------------------------

=> appel rcursif

Ex :

$ fctfactr syntaxe : fctfactr n $ fctfactr euzte12uz syntaxe : fctfactr n $ fctfactr 1 1 $ fctfactr 4 24 $

14.10.Appels de fonctions disperses dans plusieurs fichiers


Lorsque les fonctions dun programme shell sont places dans diffrents fichiers, on excute ces derniers dans lenvironnement du fichier shell principal . Cela revient excuter plusieurs fichiers shell dans un mme environnement. Dans lexemple ci-dessous, pour que la fonction f dfinie dans le fichier def_f puisse tre accessible depuis le fichier shell appel, on excute def_f dans lenvironnement de appel (en utilisant la commande interne source ou .). Seule la permission lecture est ncessaire pour def_f.

appel
----------------------------------#!/bin/bash source def_f

# ou plus court : . def_f # Permissions de def_f : r--r--r

x=2 f # appel de la fonction f contenue dans def_f -----------------------------------

105

def_f
----------------------------------#!/bin/bash function f() { echo $((x+2)) } -----------------------------------

Ex :

$ appel 4 $

106

Index
A
alias .................................................................................... 90 argument .............................................................................. 8 fonction.............................................................................. 93 fonction rcursive ............................................................ 104

I
intervalle ............................................................................ 33 invite .......................................................Voir chane dappel

B
bash ........................................................................ Voir shell blanc..................................................................................... 8

J
job ........................................................................................ 5

C
chane dappel ...................................................................... 5 code de retour..................................................................... 47 commande ............................................................................ 8 bc................................................................................ 42 cat............................................................................... 38 cmd ............................................................................. 27 declare.................................................................. 18, 75 echo .............................................................................. 9 exit.............................................................................. 50 for............................................................................... 67 function....................................................................... 93 grep ............................................................................ 48 if ................................................................................. 69 locale.......................................................................... 29 man............................................................................... 8 more ........................................................................... 43 read ............................................................................ 16 return........................................................................ 103 ruptime ......................................................................... 6 set ......................................................................... 19, 27 shift............................................................................. 21 shopt ........................................................................... 35 tee............................................................................... 43 type............................................................................. 10 unset ..................................................................... 26, 96 wc ............................................................................... 41 while ........................................................................... 56 commande compose ......................................................... 10 commande externe ............................................................. 10 commande interne ................................................................ 9 constante ............................................................................ 18

M
mta-caractres .................................................................... 8 modle ............................................................................... 55 mot ....................................................................................... 8 mot rserv........................................................................... 8

N
nom .................................................................................... 15

O
oprateur de contrle............................................................ 8 option ................................................................................... 8

P
paramtre ........................................................................... 15 paramtre de position......................................................... 21 paramtre spcial ......................................................... 20, 22 PATH..................................................... Voir variable PATH pipeline .............................................................................. 43 poubelle ............................................................................. 39 prompt.....................................................Voir chane dappel puit ..................................................................................... 39

R
redirection .......................................................................... 37 REPLY................................................. Voir variable REPLY

D
descripteur de fichier.......................................................... 37

S
script .................................................................................... 5 shell...................................................................................... 5 bash, csh, ksh, sh, tcsh, zsh .......................................... 5 sortie standard .................................................................... 37

E
ensemble ............................................................................ 33 entre standard ................................................................... 37 excution asynchrone ......................................................... 47 expression arithmtique...................................................... 76 expressions gnriques....................................................... 31 expressions rationnelles...................................................... 31 expressions rgulires ........................................................ 31

T
tube ................................................................................ 6, 42

V
variable .............................................................................. 15 PATH......................................................................... 10 REPLY....................................................................... 17

F
fichier de commandes......................................................... 13

107