Le Bourne shell sh
Le Bourne shell (sh)
Bernard Cassagne
Laboratoire de Genie Informatique
IMAG
Grenoble
novembre 1991
1
Chapter 1
Les bases
1.1 Presentation
Un interpreteur de commandes (un shell dans le jargon UNIX) est un programme qui sert
d'intermediaire entre l'utilisateur (une personne physique) et le systeme (un ensemble de
programmes).
Le service essentiel rendu par un shell est l'execution de programmes. En simpliant, un
shell execute une boucle innie sur les actions suivantes:
lecture d'une ligne
interpretation de cette ligne comme une demande d'execution d'un programme avec des
parametres.
lancement de ce programme avec passage des parametres.
Par exemple, si l'on tape:
grep resu main.c
le shell interprete cela comme etant la demande d'execution du programme grep avec les
parametres resu et main.c.
Tous les autres services oerts par le shell n'ont d'autre but que de faciliter cette t^ache
fondamentale qu'est l'execution de programme.
Parmi les autres services de base du shell, on rencontre essentiellement:
la generation de noms de chiers
la redirection des entrees-sorties
la possibilite d'execution en avant plan ou en arriere plan.
la possibilite d'executer plusieurs programmes en parallele en les faisant cooperer selon
la technique du travail a la cha^ne.
la gestion de variables
la substitution de commandes
les chiers de commandes
2
1.2 L'execution de programme
1.2.1 Programmes et parametres
Quand le shell analyse une ligne de commande, il decoupe cette ligne en mots separes par des
blancs. Une fois ce decoupage realise, le premier mot de la ligne est interprete comme etant le
nom d'un chier a executer, les autres mots sont consideres comme des parametres a passer
au programme. Le shell ne plaque aucune semantique sur les parametres, pour lui se sont de
simples chaines de caracteres. C'est la commande appelee qui aectera une semantique aux
parametres. Par exemple:
grep -i alloc names.c
le shell passe les chaines de caracteres -i, alloc, names que grep interpretera respectivement
comme etant:
1. une option (-i) signiant ne pas faire de dierence entre majuscules et minuscules
2. une cha^ne de caracteres (alloc) : la cha^ne a rechercher
3. un nom de chier (names.c) : le chier dans lequel proceder a la recherche.
1.2.2 Parametres formes de plusieurs mots
Il arrive parfois que la maniere dont le shell decoupe la ligne en parametres ne satisfasse pas
l'utilisateur. Supposons que l'on ait cree un cher qui soit un annuaire de telephone. Il est
forme d'un ensemble de lignes de la forme suivante:
Jacques Eudes 9056
Serge Rouveyrol 4567
Si ce chier a pour nom annuaire, quand on desire obtenir un numero de telephone, il sut
de faire:
$ grep -i rouveyrol annuaire
Serge Rouveyrol 4567
$
Mais pourquoi ne peut on pas faire:
$ grep -i serge rouveyrol annuaire
rouveyrol: No such file or directory
annuaire:Serge Rouveyrol 4567
$
on voulait rechercher la cha^ne serge rouveyrol dans le chier annuaire. Mais le shell n'a
pas compris que pour nous serge rouveyrol forme un tout, il a passe a grep 4 parametres
qu'il a interprete de la maniere suivante: serge : cha^ne a rechercher, rouveyrol et annuaire
: noms de chiers dans lesquels proceder a la recherche. Le message d'erreur indique qu'il n'a
(et pour cause) pas trouve de chier de nom rouveyrol.
Pour resoudre ce probleme, il faut indiquer au shell que les mots serge et rouveyrol,
bien que separes par un blanc, forment un seul parametre. Cela se realise en entourant le
parametre de deux caracteres ' (simple quote), comme ceci:
3
$ grep -i 'serge rouveyrol' annuaire
Serge Rouveyrol 4567
$
A la place du caractere ', on peut aussi utiliser le caractere " (double quote).
$ grep -i "serge rouveyrol" annuaire
Serge Rouveyrol 4567
$
1.2.3 Interpretation des blancs
La phase consistant pour le shell a decouper une ligne de commande en nom de programme et
parametres porte le nom d'interpretation des blancs. En eet, chaque blanc est interprete en
fonction du contexte dans lequel il se trouve: un blanc est un separateur de mot a l'exterieur
des quotes, mais pas a l'interieur.
Le caractere espace n'est pas le seul caractere \blanc". Les caracteres blancs sont contenus
dans la variable IFS (Internal Field Separator) et sont par defaut l'espace, la tabulation et le
caractere (line-feed).
1.3 Generation de noms de chiers
1.3.1 Presentation
Travailler avec le shell necessite de manipuler a tout instant des noms de chier : l'activation
d'une commande necessite le plus souvent de lui passer en parametre un ou plusieurs noms de
chiers. Il est donc agreable que le shell ore des moyens puissants de designation de chiers.
Supposons que l'on ait un repertoire contenant quelques dizaines de chiers que l'on desire
detruire. Taper un par un les noms de chiers pour les donner en parametre a la commande
rm (remove) serait tr
es peu ergonomique. On sent donc bien le besoin de pouvoir exprimer :
rm tous-les-chiers.
Le shell sh a adresse ce probleme dont la solution porte le nom technique de generation
de noms de chiers. Elle passe par l'utilisation d'un certains nombre de caracteres servant a
construire des modeles. Un modele permet de designer un ensemble de noms de chiers.
Il existe trois constructeurs de modeles qui sont *, ? et [].
1.3.2 Le constructeur *
Un modele de la forme X*Y ou X et Y sont des cha^nes quelconques de caracteres, eventuellement
nulles, designe l'ensemble des noms de chiers de la forme XUY ou U est une cha^ne de caracteres quelconques eventuellement nulle.
Exemple:
*
designe tous les chiers
toto* d
esigne tous les chiers commencant par toto
*.c
designe tous les chiers se terminant par .c
*/*.c d
esigne tous les chiers se trouvant dans un repertoire quelconque et se terminant par .c
4
1.3.3 Le constructeur ?
Un modele de la forme X?Y ou X et Y sont des cha^nes quelconques de caracteres, eventuellement
nulles, designe l'ensemble des noms de chiers de la forme XuY ou u est un caractere quelconque.
?
designe tous les chiers dont le nom comporte un seul caractere
fic.? d
esigne tous les chiers de type fic.x
1.3.4 Le constructeur []
Un modele de la forme X [abc...z ]Y ou X et Y sont des cha^nes quelconques de caracteres,
eventuellement nulles, et abc...z une cha^ne litterale de caracteres, designe l'ensemble des
noms de chiers ayant l'une des formes suivantes: XaY ou XbY ou ... ou XzY.
Dans le cas ou l'ensemble des caracteres abc ... z forment une suite continue lexicographiquement, on peut utiliser la raccourci d'ecriture suivant : a-z. On peut de surcroit
melanger les deux techniques, par exemple utiliser [a-z.;,]
Exemples:
[a-z].[0-9] d
esigne tous les chiers de type a.0 a.1 ... b.0 b.1 etc ...
Particularite du sh System V
Le sh de UNIX Systeme V, par opposition a celui de UNIX BSD a la possibilite de mettre le
signe ! juste apres le [ pour designer non pas l'ensemble des caracteres entre crochets, mais
le complement de cet ensemble
Exemples:
*[!a-z] d
esigne les chiers se terminant par autre chose qu'une lettre
1.3.5 Mise en uvre de la generation de noms de chiers
Apres avoir decoupe une commande en mots, le shell scrute chaque mot a la recherche des
metacaracteres * ? [ ]. Si un mot comporte un metacaractere, il est considere comme
un modele, la generation de noms de chiers est declenchee, et le modele est remplace par
l'ensemble des noms de chiers qu'il designe. Ces noms sont classes par ordre alphabetique.
Exemple:
$ ls -l texinfo*
-rw-r--r-- 1 bernard
-rw-r--r-- 1 bernard
-rw-r--r-- 1 bernard
-rw-r--r-- 1 bernard
-rw-r--r-- 1 bernard
-rw-r--r-- 1 bernard
$
4035
50848
51697
52123
26458
188731
Oct
Oct
Oct
Oct
Oct
Oct
10
10
10
10
10
10
11:10
11:10
11:10
11:10
11:10
11:09
texinfo
texinfo-1
texinfo-2
texinfo-3
texinfo-4
texinfo.texinfo
1.4 Redirection des entrees-sorties
Un programme s'executant sous UNIX dispose, pour realiser ses entrees-sorties, d'un certain
nombre de peripheriques logiques reperes par un numero de 0 a N. Parmi ces peripheriques
logiques, trois sont particularises:
5
Le peripherique logique 0 a pour vocation de realiser des entrees, on le nomme entree
standard, il est aecte par defaut au clavier du terminal.
Le peripherique logique 1 a pour vocation de realiser des sorties, on le nomme sortie
standard, il est aecte par defaut a l'ecran du terminal.
Le peripherique logique 1 a pour vocation d'^etre le support des mesages d'erreurs, on le
nomme erreur standard, il est aecte par defaut a l'ecran du terminal.
L'expression \a pour vocation de" signie qu'il s'agit d'une norme d'utilisation des peripheriques
logiques, mais rien dans le noyau UNIX oblige a les utiliser de cette facon.
Un grand nombre de programmes se contentent de lire un ot de donnes, de faire un
traitement sur ces donnees et d'ecrire un ot de donnees resultat. Ces programmes prennent
donc leurs donnees sur l'entree standard et ecrivent leurs resultats sur la sortie standard. Un
programme qui respecte cette convention porte (dans le jargon UNIX) le terme de ltre. On
a donc le schema suivant:
entree standard
(clavier)
+-------+
|
|
---> | prog | --->
|
|
+-------+
sortie standard
(ecran)
Prenons comme exemple bc (binary calculator), il lit une ligne au terminal, interprete cette
ligne comme etant une expression a calculer, calcule l'expression et imprime le resultat sur le
terminal. Voici un exemple d'utilisation interactive de bc:
$ bc -l
456 + 1267
1723
84 * 35
2940
quit
$
(L'argument -l permet d'avoir une plus grande precision dans les divisions).
On peut cependant imaginer beaucoup de situation ou l'on aimerait activer bc en lui
faisant lire les expressions non pas a partir du terminal, mais a partir d'un chier. Imaginons par exemple que l'on desire faire des statistiques de vitesse sur des communications.
Supposons que les communications sont gerees par un logiciel qui ecrit des messages dans un
chier de log, messages qui ont la forme suivante:
from pad: 1254 characters transmitted in 34 seconds
from pad: 687 characters received in 23 seconds
A l'aide d'un editeur il est facile de transformer ce chier de facon a remplacer chaque ligne
par l'expression : nombre de caracteres divise par nombre de secondes. Sous vi cela peut se
faire en 3 commandes:
:%s/^[^0-9]*//
:%s+car.*in+/+
:s/ seconds//
6
Ces trois commandes agissent sur l'ensemble des lignes du chier (%). La premiere substitue
l'ensemble des caracteres n'etant pas des chires ([^0-9] et commencant au debut de la ligne
(^), par le vide. La seconde remplace la cha^ne debutant par car et se terminant en in par
le signe de la division (/). La troisieme remplace la cha^ne espace seconds par le vide.
Notre chier se trouve alors transforme en:
1254 / 34
687 / 23
Pour faire calculer ces expressions par bc, il sut de l'activer en lui faisant prendre le ot
de donnees d'entree non pas a partir du terminal, mais a partir du chier qui les contient,
par exemple data. Cela se fait de la maniere suivante:
$ bc -l < data
36.88235294117647058823
29.86956521739130434782
$
Si le chier a une taille de l'ordre du millier de lignes, on voit le temps gagne.
Ce que nous avons realise avec bc est general: le fait d'executer une commande suivie du
signe < suivi d'un nom de chier, a pour eet de rediriger l'entree standard de cette commande
a partir du chier indique.
On peut de la m^eme maniere rediriger la sortie standard d'un programme vers un chier
en faisant suivre la commande du signe > suivi d'un nom de chier. Par exemple:
ls > fics
mettra le resultat de la commande ls dans le chier fics.
On peut combiner les deux mecanismes et rediriger a la fois l'entree et la sortie d'un
programme. Par exemple:
$ bc -l < data > resu
$
est active en lisant les expressions dans le chier data et en ecrivant les resultats dans le
chier resu.
bc
1.5 Execution en sequence
Il est possible de demander l'execution en sequence de plusieurs commandes. Cela s'obtient
a l'aide de l'operateur ; (point virgule). Exemple:
cd src; ls -l
1.6 Execution en premier plan ou en arriere plan
Lorsqu'on demande l'execution d'une commande, le shell lance la commande et se met en
attente de sa terminaison. Ceci est mis en evidence aux yeux de l'utilisateur par le fait que le
shell n'imprime un prompt que lorsque la commande en cours est terminee. Quand on travaille
7
de cette maniere on dit que l'on execute les programmes en premier plan (foreground). Dans la
grande majorite des cas, les commandes ont une duree d'execution courte et cette technique
est bien adaptee. Il existe par contre certaines commandes qui demandent un long temps
d'execution comme des compilations de gros chiers par exemple. Si ces executions ne sont
pas interactives, attendre la n de leur execution est une perte de temps. Il existe donc une
possibilite pour l'utilisateur de demander au shell de lancer l'execution d'un programme et
de ne pas attendre la n de son execution. L'utilisateur pourra alors continuer a interagir
avec le shell pendant que le programme s'execute. Quand on execute un programme de cette
facon, on dit qu'on l'execute en arriere plan (dans le background). Pour demander ce service,
il sut de taper le caractere & a la n de la commande. Exemple:
$ cc -o essai essai.c &
On peut combiner redirection des entrees-sorties et mise en t^ache d'arriere plan. C'est
m^eme necessaire si le programme realise des sorties, car sinon elles se melangeraient avec les
sorties du programme en cours. Dans l'exemple suivant, on lance un tri en arriere plan en
redirigeant la sortie standard sur le chier donnees_triees
$ sort donnees_brutes > donnees_triees &
1.7 Travail a la cha^ne
Nous avons vu qu'un programme lisait de l'information sur son entree standard, eectuait un
certain traitement et ecrivait le resultat sur sa sortie standard. Il arrive tres souvent que l'on
desire faire cooperer deux programmes de maniere a ce que le second eectue son travail sur
l'information produite par le premier selon le schema suivant:
entree
+-------+
+-------+
|
|
|
|
---> | Pg1 | ----------> | Pg2 | --->
|
|
|
|
+-------+
+-------+
sortie
Une telle organisation est ce que l'on appelle communement du travail a la cha^ne.
Pour realiser cela, le systeme etabli un tampon entre les deux programmes, et connecte
la sortie du premier programme a l'entree du tampon, et l'entree du second programme a la
sortie du tampon. Dans le jargon UNIX, un tel tampon porte le nom de pipe.
On a alors le schema suivant:
+-------+
|
|
entree ---> | Pg1 |
|
|
+-------+
pipe
+-----------+
---> |
|
+-----------+
--->
+-------+
|
|
| Pg2 |
|
|
+-------+
---> sortie
Le shell permet de creer deux programmes s'executant selon une telle methode. Il sut
de taper les textes d'activation des deux commandes separes par le signe conventionnel | qui
demande l'etablissement d'un pipe. On aura donc: commande1 | commande2
8
Voyons un exemple pratique d'utilisation. Supposons que l'on travaille sur une grosse
machine sur laquelle plusieurs dizaines d'utilisateurs sont connectes. On desire savoir si une
certaine personne est actuellement connectee. Il existe une commande who qui donne la liste
des utilisateurs connectes:
$ who
bernard
eudes
langue
mounier
henzinge
$
ttyp0
ttyp3
ttyp8
ttyp9
ttypa
Oct
Oct
Oct
Oct
Oct
16
18
19
19
19
13:00
12:06
16:03
11:41
14:05
Si la liste est tres longue, il est dicile de reperer a l'il la personne cherchee. Faisons faire
le travail par la machine:
$ who | grep eudes
eudes
ttyp3
Oct 18 12:06
$
1.7.1 Notion de pipe-line
La technique que nous venons de voir peut se generaliser a un nombre quelconque de programmes. Exemple:
prog1
|
prog2
|
prog3
|
prog4
Un ensemble de programmes connectees par pipes porte le nom de pipe-line.
Du point de vue de la redirection des entrees-sorties, il est possible de rediriger l'entree
standard du premier programme, et la sortie standard du dernier: pipe-line:
prog1
<
data_in
|
prog2
|
prog3
|
prog4
>
data_out
>
data_out
Un pipe-line peut egalement ^etre execute en arriere plan:
prog1
<
data_in
|
prog2
|
prog3
|
prog4
&
1.8 Les variables
Le shell permet de manipuler des variables. Les variables n'ont pas besoin d'^etre declarees, et
elles n'ont pas de type (au sens des langages de programmation). En eet, elles ne peuvent
avoir comme valeur que des objets d'un seul type: des cha^nes de caracteres. Pour aecter
une valeur a une variable il sut de taper le nom de la variable, suivi du signe =, suivi de la
valeur que l'on desire aecter a la variable. Par exemple:
MBOX=/users/bernard/mbox
Attention a ne pas laisser de blanc autour du caractere =.
Pour referencer la valeur d'une variable, on utilise la notation consistant a ecrire le signe
$ suivi du nom de la variable. Par exemple:
9
vi $MBOX
resultera en un vi /users/bernard/mbox. Le travail du shell consistant a remplacer $nomde-variable par la valeur de la variable, porte le nom de substitution de variable.
En travail interactif, les variables sont tres utiles pour faire des abreviations. Supposons que l'on ait besoin d'agir de maniere repetee sur les chiers donnees_brutes et
donnees_triees, on peut se d
enir les variables:
F1=donnees_brutes
F2=donnees_triees
il sera ensuite agreable de pouvoir referencer ces noms par $F1 et $F2.
On peut egalement s'en servir pour faire des abreviations de commandes completes:
CC='cc -o essai essai.c'
$ $CC
"essai.c", line 3: i undefined
$
Dans tous les exemples donnes les noms de variables sont en majuscules, mais cela n'est
nullement une obligation.
1.9 La substitution de commande
La substitution de commande consiste a ecrire une commande entouree du signe ` (back
quote). On prendra garde a ne pas confondre ce caractere avec le caractere ' (simple quote).
Sur rencontre d'une commande entouree du signe `, le shell execute la commande et remplace
le texte de la commande par sa sortie (le texte produit par son execution). Exemple:
$ pwd
/users/lgi/systemeV/bernard/enseignement
$ D=`pwd`
$ echo $D
/users/lgi/systemeV/bernard/enseignement
$ ls texinfo*
texinfo texinfo-2 texinfo-4 texinfo-1 texinfo-3 texinfo.texinfo
$ FICS=`ls texinfo*`
$ echo $FICS
texinfo texinfo-1 texinfo-2 texinfo-3 texinfo-4 texinfo.texinfo
1.10 Les chiers de commandes
1.10.1 Presentation
Il arrive souvent que l'on fasse du travail repetitif necessitant de taper souvent les m^emes
commandes enchainees. Il est alors agreable de pouvoir mettre une fois pour toutes ces
commandes dans un chier, et d'invoquer ensuite le chier provoquant ainsi l'execution des
commandes comme si on les avaient tapees au terminal. Un tel chier est dit \chier de
commandes" et s'appelle un shell script dans le jargon UNIX.
10
Supposons que l'on soit en train de mettre au point un programme de nom gestion_notes.c,
on tape souvent les commandes de compilation et d'execution. Il peut ^etre interessant de mettre dans un chier de nom RUN (par exemple) les lignes suivantes:
cc -o gestion_notes gestion_notes.c
gestion_notes
Pour executer ce chier de commandes, on peut activer sh en le lui passant en parametre,
comme ceci:
$ sh gestion_notes
Ceci aura pour eet d'encha^ner la compilation et l'execution du programme gestion_notes.
Il existe une autre methode qui permet d'executer un chier de commandes en l'invoquant
de la m^eme maniere que l'on invoque un programme binaire. Il faut d'abord donner le droit
d'execution au chier de commandes:
$ chmod +x RUN
$
Pour l'executer, il sut ensuite de taper:
$ RUN
1.10.2 Passage de parametres
Il est possible de passer des parametres a un chier de commandes. Dans un chier de
commandes les neuf premiers parametres sont des variables portant les noms 1, 2, ... 9. A
l'interieur du chier de commandes on les reference donc par $1, $2, ... $9. Si nous voulions
parametrer le chier de commandes RUN, nous l'ecririons de la maniere suivante:
cc -o $1 $1.c
$1
et nous pourrions l'invoquer par:
RUN gestion_notes
Il n'y a pas de moyen de referencer directement les parametres au-dela du neuvieme. On
verra plus loin (cf commande interne shift, chapitre 4.10) comment il faut proceder. Par
contre, il y a un moyen de referencer tous les parametres: c'est la variable *.
$ cat VARETOILE
echo $*
$ VARETOILE f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
$
Enn, il faut savoir que le variable 0 est positionnee avec le nom du chier de commandes
qui est execute:
$ cat VARZERO
echo $0
$ VARZERO f1
VARZERO
$
11
1.10.3 Le shell d'execution
Il existe dans le monde UNIX plusieurs shells. Les plus connus sont sh, csh, ksh et tcsh. Les
deux shells de base sont sh et csh. Les shells ksh et tcsh sont respectivement des extensions
de sh et csh. Quand on execute un chier de commandes simplement en invoquant son nom,
le shell interactif que l'on utilise va lancer l'execution d'un shell identique a lui-m^eme pour
executer le chier de commandes. Il y a un moyen de forcer le shell d'execution du chier de
commandes en mettant en t^ete de celui-ci la ligne :
#!/bin/sh
ou:
#!/bin/csh
selon le shell desire.
Comme on est jamais s^ur, quand on ecrit un chier de commandes, du shell qui sera utilise
lors de son execution, c'est une bonne habitude de toujours mettre une telle ligne en t^ete du
chier.
1.11 Le probleme des metacaracteres
En faisant le tour de l'ensemble des mecanismes qu'ore le shell, nous avons vu que chaque
mecanisme repose sur un ensemble de metacaracteres. La generation des noms de chiers
fonctionne avec *, ? et [], la redirection des entrees-sorties avec > et < etc ... Ceci ore
le grand avantage que l'on peut exprimer rm tous-les-chiers par rm *, mais comment faire
quand je veux faire rm sur un chier dont le nom est *? En d'autres termes, comment denoter
de maniere litterale les metacaracteres?
Il y a plusieurs solutions a ce probleme.
Solution 1:
Solution 2:
Solution 3:
le caractere \ est un metacaractere signiant que le caractere qui suit doit
^etre pris de maniere litterale. Par exemple, \* signie * et non pas tous-leschiers. Autre exemple, \a signie a. Attention, \ n'a ce sens qu'a l'exterieur
des cha^nes entourees du caractere ' ou du caractere ".
tous les caracteres entoures par ' (simple quote) doivent ^etre pris de maniere
litterale. Par exemple, '*?[]' sigie *?[] et '\a' signie \a.
dans une cha^ne de caracteres entouree du signe " (double quote) tous les caracteres doivent ^etre pris de maniere litterale sauf les caracteres $ ` \ (dollar,
back quote et back slash). Cela signie que le shell continue a faire la substitution de variables, la substitution de commandes a l'interieur d'une telle
cha^ne. D'autre part, le caractere \ a le sens de rendre litteral le caractere
suivant sur les SEULS caracteres $ ` \ ". Un \ suivi d'un line-feed sert de
continuateur de ligne: les deux caracteres sont ignores.
$ ls
texinfo texinfo-1 texinfo-2 texinfo-3 texinfo-4 texinfo.texinfo
$ echo *
12
texinfo texinfo-1 texinfo-2 texinfo-3 texinfo-4 texinfo.texinfo
$ V=bonjour
$ echo '* $V \* \$'
* $V \* \$
$ echo "* $V \* \$"
* bonjour \* $
$
On fera attention a la subtile dierence de fonctionnement du \ selon le contexte dans
lequel on le trouve: a l'exterieur ou a l'interieur de cha^nes entourees de ' ou de ".
$ echo \a \$
a $
$ echo '\a \$'
\a \$
$ echo "\a \$"
\a $
$
13
Chapter 2
L'execution de programme
2.1 Rappel sur le systeme de chier UNIX
Le systeme de chiers UNIX est b^ati sur le modele de l'arborescence. Les objets terminaux
sont essentiellement les chiers, et les nuds de l'arborescence sont des repertoires. Un objet
dans le systeme de chiers est designe par un nom de chemin. Un nom de chemin est un
chemin dans l'arborescence, allant jusqu'a l'objet a designer. Les noms de chemin peuvent
^etre de deux types selon le repertoire qui est pris comme point de depart:
relatifs:
absolus:
le point de depart est le repertoire courant.
le point de depart est la racine de l'arborescence.
Par exemple, si le repertoire courant est /usr/local, l'objet /usr/local/src/tex peut
^etre designe par le nom de chemin relatif src/tex ou par le nom de chemin absolu /usr/local/src/tex.
2.2 Recherche du chier a executer
Nous avons vu qu'une commande est formee du nom du chier a executer, suivi des parametres.
En ce qui concerne le nom du chier a executer, le shell distinge deux cas:
1. ce nom est forme de plusieurs composants (il comporte au moins une fois le separateur
/). Dans ce cas, le shell le consid
ere comme un nom de chemin et l'interprete de la
maniere habituelle.
2. ce nom est forme d'un seul composant (il ne comporte pas le separateur /). Dans ce cas,
le shell interprete ce nom comme etant un nom de chier a rechercher dans un ensemble
de repertoires. La liste des noms de ces repertoires est contenue dans la variable PATH.
Exemple de variable PATH:
$ echo $PATH
/usr/local/bin:/usr/ucb:/usr/bin:/bin:.
$
14
On voit que par convention, dans la variable PATH, les repertoires sont separes par le signe :
(deux points). De plus, le signe . (point) designe le repertoire courant.
Pour un utilisateur ayant une telle variable PATH, et demandant a executer le programme
awk, le shell recherchera ce chier dans les r
epertoires suivants, dans l'ordre indique:
1. /usr/local/bin
2. /usr/ucb
3. /usr/bin
4. /bin
5. le repertoire courant.
Le shell lancera l'execution du premier chier trouve repondant aux deux conditions suivantes: s'appeler awk et avoir le droit d'execution (droit x).
Il est classique qu'une installation redenisse de maniere locale certaines commandes qui
sont mises dans /usr/local/bin. Il sut de mettre ce repertoire au debut de son PATH
pour que cela cache les commandes standards de m^eme nom. Ces dernieres restent cependant
accessibles en utilisant une designation absolue. Supposons que l'administrateur systeme ait
genere une nouvelle version de awk qu'il ait mise dans /usr/local/bin, la version standard
sera utilisable en l'invoquant par /bin/awk.
De la m^eme maniere, il est classique que les utilisateurs developpent des outils personnels,
ou fassent des versions personnelles de commandes standard, et les mettent dans un repertoire
bin dans leur r
epertoire d'origine. Il leur sut de mettre ce repertoire en t^ete de leur PATH
pour pouvoir acceder a ces nouvelles commandes.
Supposons un utilisateur ayant /users/bernard comme repertoire d'origine, il lui sut
de faire:
$ PATH=/users/bernard/bin:$PATH
$
pour pouvoir acceder aisement a ses commandes personnelles. En eet:
$ echo $PATH
/users/local/bin:/usr/local/bin:/usr/ucb:/usr/bin:/bin:.
$
2.3 Variable PATH et securite
Il y a une raison qui invite a mettre le repertoire courant en t^ete dans sa variable PATH, c'est
la mesaventure suivante. La premiere chose que fait un debutant avec UNIX est de creer un
petit programme et d'essayer de l'executer. Et comment appeller ce programme? test, bien
s^ur. Ce que cette personne ne sais pas, c'est qu'il existe dans le systeme une commande qui
s'appelle test, elle reside sous /bin. Si /bin se trouve avant . dans la variable PATH, sur
invocation de test, c'est la commande systeme qui sera executee et non pas le programme de
l'utilisateur. On peut passer beaucoup de temps a comprendre pourquoi ce si petit programme
de test refuse absolument de marcher ...
15
Ce serait cependant une enorme breche dans la securite que de mettre le repertoire courant
en t^ete et non pas en queue de sa variable PATH. En eet, on n'execute pas toujours des
programmes en restant dans son arborescence personnelle, parfois on fait cd pour aller ailleurs.
Or certains repertoires orent le droit w (ecriture) a tout le monde, c'est le cas par exemple
de /tmp. Imaginons que vous vous positionniez sur /tmp et que vous fassiez ls apres qu'une
personne mal intentionnee ait mis dans ce repertoire un chier de nom ls, que va-t-il se
passer? Si le repertoire courant est en t^ete de votre variable PATH vous allez executer le ls de
/tmp. Et maintenant que se passe-t-il si le chier ls est un chier de commandes qui contient:
cd $HOME
rm -r *
Il faut donc resister a l'envie de mettre le repertoire courant en t^ete de son PATH et bien
garder a l'esprit que quand on invoque une commande simplement par son nom, elle est
recherchee dans un ensemble de repertoires et que le repertoire courant est le dernier. Pour
executer un programme test du repertoire courant, il sut de l'invoquer par ./test.
2.4 Variable PATH et environnement BSD ou System V
Il existe deux grandes familles de systemes UNIX: ceux de type BSD (de l'universite de
Californie a Berkeley), et ceux de type System V (de ATT). Ces deux familles ont un anc^etre
commun, mais elles ont diverge 1 . Entre les deux familles il y a beaucoup de choses en
commun, mais aussi beaucoup de petites dierences horripilantes. Certains contructeurs qui
veulent orir a la fois un environnement BSD et System V, mettent dans l'arborescence de
leur machine les commandes des deux versions. Il est traditionnel d'avoir sous /usr/ucb des
commandes Berkeley, et de mettre dans /usr/5bin les commandes System V.
En jouant sur l'ordre des repertoires dans la variable PATH, on peut donner a l'utilisateur
l'impression qu'il est dans un environnement Berkeley ou System V.
2.5 Passage de parametre a un programme
Un programme qui desire recuperer les parametres passes par le shell doit ^etre programme de
la maniere suivante:
void main(argc,argv)
int argc;
char *argv[];
{
...
}
argc a pour valeur 1 + le nombre de param
etres et argv est un tableau de pointeurs vers
les parametres contenus dans des cha^nes de caracteres. argv[1] pointe vers le premier
parametre, argv[2] pointe vers le deuxieme parametre, etc... et argv[0] pointe vers une
cha^ne de caracteres contenant le nom du programme execute. Le parametre argc a donc
pour valeur le nombre d'elements du tableau argv.
A titre d'exemple, voici un programme qui imprime les valeurs de argc et argv:
1
L'une est devenue un singe, l'autre un homme
16
$ cat printargs.c
main(argc,argv)
int argc;
char *argv[];
{
int i;
printf("argc vaut %d\n",argc);
for (i = 0; i < argc; i++)
printf("arg %d = |%s|\n",i,argv[i]);
}
$
Et maintenant une execution de ce programme:
$ printargs hello + 34 %
argc vaut 5
arg 0 = |printargs|
arg 1 = |hello|
arg 2 = |+|
arg 3 = |34|
arg 4 = |%|
$
Montrons que les blancs ne sont pas signicatifs (ceci vient de la phase dite d'interpretation
des blancs:
$ printargs
argc vaut 5
arg 0 = |printargs|
arg 1 = |hello|
arg 2 = |+|
arg 3 = |34|
arg 4 = |%|
$
hello
+
34
Une autre execution mettant en evidence l'eet des divers quotes:
$ printargs 'hello world'
argc vaut 4
arg 0 = |printargs|
arg 1 = |hello world|
arg 2 = |+|
arg 3 = |bonjour a tous|
$
\+
"bonjour a tous"
Exemple de parametres nuls:
$ printargs '' hello ""
argc vaut 4
17
%
arg
arg
arg
arg
$
0
1
2
3
=
=
=
=
|printargs|
||
|hello|
||
2.6 Programmes et processus
Les utilisateurs ne raisonnent generalement qu'en terme de programme, mais il est necessaire
de bien comprendre la notion de processus, sinon un certain nombre de comportements du
shell resteront incomprehensibles.
Un programme peut se denir comme etant un algorithme. Cet algorithme peut ^etre
sous la forme d'un programme source ou d'un programme compile, pr^et a ^etre execute par la
machine.
Un processus peut se denir comme etant un programme en cours d'execution. Un programme donne n'existe generalement qu'en un exemplaire dans une machine, mais il peut
donner naisance a un nombre indetermine de processus qui l'executent en m^eme temps.
Il y a une commande qui permet a un utilisateur de voir quels sont les processus que la
machine execute pour lui, c'est la commande ps.
$ ps
PID TTY
28061 p9
$
TIME COMMAND
0:19 sh
Ce processus est le shell /bin/sh que l'on utilise de maniere interactive.
La commande ps admet un parametre -a qui lui demande de lister tous les processus
m^eme ceux des autres utilisateurs. Si on l'utilise, on voit qu'il y a beaucoup de processus qui
s'executent sur la machine, et qu'en particulier il y a beaucoup de processus qui executent
un shell (sh, csh, ksh ou tcsh). Le systeme lance en eet un processus shell pour chaque
utiisateur connecte a la machine.
2.6.1 Programmes binaires
Maintenant, lancons un programme en arriere plan, et essayons de le voir avec ps. Pour cela,
il faut que son execution soit un peu longue de maniere a ce qu'on ait le temps de taper ps
avant qu'il ne soit termine. En voici un tres long:
$ ls -lR / > fichiers &
28104
$ ps
PID TT STAT TIME COMMAND
28061 p9
0:19 sh
28104 p9 D
0:02 ls -lR /
28105 p9 1
0:00 ps
$ kill 28104
$
18
On voit que la commande dont nous avons demande l'execution s'execute dans un processus.
Il y a toujours le processus sh et egalement ps. Sit^ot le ps realise, nous avons tue le ls qui
sinon aurait encombre inutilement la machine.
Executons maintenant un pipe-line:
$ ls -lR / | wc -l
28134
$ ps
PID TT STAT TIME
28061 p9
0:19
28134 p9 S
0:00
28135 p9 R
0:00
28136 p9 1
0:00
$ kill 28134
&
COMMAND
sh
wc -l
ls -lR /
ps
On voit que les deux commandes qui participent au pipe-line s'executent chacune dans un
processus. Ceci est une regle generale: le shell cree un processus pour toute commande que
l'utilisateur demande d'executer.
2.6.2 Fichier de commandes
Essayons de comprendre ce qui se passe quand on execute un chier de commandes. Creons
par exemple un chier de commandes de nom LS et contenant simplement ls -lR / > fichier
et executons-le en programme d'arriere plan:
$ chmod +x LS
$ LS &
28192
$ ps
PID TT STAT
28061 p9
28192 p9 S
28193 p9 0
28194 p9 1
$ kill 28193
$
TIME
0:19
0:00
0:00
0:00
COMMAND
sh
sh
ls -lR /
ps
On voit que l'execution des commandes du chier LS se fait grace a un autre processus qui
execute sh. C'est le shell courant qui a lance une autre invocation de lui-m^eme pour executer
le chier de commandes. Un tel shell est appele un sous-shell. Ce sous-shell est en attente de
la terminaison de la commande ls qu'il a lance. Par le fait qu'un chier de commandes est
interprete par un autre shell, un chier de commandes peut ^etre execute en arriere plan tout
comme un programme binaire.
2.6.3 Fichier de commandes execute par le shell courant
Il est possible de faire executer un chier de commandes par le shell courant et non pas par
un sous-shell. Il faut pour cela utiliser la commande interne . (point). Executer un chier de
commandes de cette maniere est necessaire quand on desire que des aectations de variables
realisees dans le chier de commandes aectent les variables du shell courant. Exemple:
19
$ cat modvars
#!/bin/sh
V1=1
V2=2
$ echo $V1 $V2
$ modvars
$ echo $V1 $V2
$ . modvars
$ echo $V1 $V2
1 2
$
Quand on realise une modication au chier .profile ayant pour but de changer les valeurs
aectees aux variables gerees par .profile, si on veut que ces modications aectent le shell
courant, il faut executer le chier .profile par la commande interne ..
$ echo $PATH
/usr/ucb:/usr/bin:/bin:.
$ vi $HOME/.profile
#
pour changer la valeur de PATH
$ . .profile
$ echo $PATH
/usr/local/bin:/usr/ucb:/usr/bin:/bin:.
2.6.4 En resume
La maniere dont le shell lance des processus peut ^etre resume dans les regles suivantes:
1. Tout programme est execute par un processus. En particulier, les dierents composants d'un pipe-line sont executes par des processus dierents, c'est ce qui assure
leur execution en parallele.
2. Quand le shell lance l'execution d'un programme en avant plan, il attend la n de son
execution ; quand il lance un programme en arriere plan, il n'attend pas la n de son
execution.
3. Quand un chier de commandes est execute par une invocation de son nom, le shell cree
un autre processus shell. C'est ce sous-shell qui interpretera les commandes du chier.
4. Quand un chier de commandes est execute par la commande interne . (point), il
n'y a pas creation d'un autre processus shell. C'est le shell courant qui interprete les
commandes du chier.
20
Chapter 3
La redirection des entrees-sorties
Pour comprendre l'ensemble des mecanismes de redirection oerts par le shell il est necessaire
de connaitre un minimum de choses sur la philosophie des services d' entrees-sorties oerts
par le noyau UNIX.
3.1 Rappels sur le noyau UNIX
3.1.1 Les primitives d'entrees-sorties
Le noyau UNIX ore essentiellement deux primitives read et write qui ont toutes les deux
le m^eme interface:
int read(fd,buffer,nboct)
char *buffer;
int fd,nboct;
int write(fd,buffer,nboct)
char *buffer;
int fd,nboct;
fd est un peripherique logique.
buer est un tableau de caracteres
nboct est le nombre de caracteres du tableau
Quand on execute un operation de read ou write, le peripherique logique sur laquelle elle
porte doit ^etre aecte a un peripherique ou a un chier. La primitive du noyau UNIX qui
permet de realiser une telle aectation est open (sur un peripherique ou un chier), qui rend
un numero de peripherique logique que l'on referencera lors de toute entree sortie ulterieure.
Le squelette d'un programme faisant des entrees-sorties est donc:
fd = open("data",O_RDONLY,0);
...
read(fd,buffer,nboct);
...
close(fd);
21
3.1.2 La notion de le descriptor
Dans le jargon UNIX ce que nous avons appele un peripherique logique porte le nom de le
descriptor. C'est un terme assez malheureux dans la mesure ou ce n'est pas ce que l'on appelle
communement un descripteur de chier. Ce que l'on entend habituellement par descripteur
de chier correspond a la notion UNIX de i-node. Dans tout ce manuel nous nous tiendrons
cependant a ce terme de le descriptor de maniere a ce que le lecteur ne soit pas desoriente
en lisant la documentation anglaise du systeme.
3.1.3 Peripheriques physiques et chiers
Le systeme UNIX unie (du point de vue des primitives du systeme) la notion de peripherique
physique et la notion de chier. En eet, tout peripherique physique a un descripteur dans
l'arborescence de chiers. Ce descripteur peut ^etre designe au moyen d'un nom de chemin,
comme un chier. Traditionnelement, les descripteurs de peripheriques resident dans le
repertoire /dev. Un derouleur de bandes pourra avoir un descripteur designe par /dev/mt0,
et un programme pourra aecter ce peripherique a un le descriptor en faisant:
fd = open("/dev/mt0",... );
les entrees-sorties ulterieures utilisant le le descriptor fd auront lieu sur ce derouleur de
bandes. Dans tout ce qui suit, pour eviter la lourdeur, nous ne diront pas \peripherique
physique ou chier", mais simplement \chier".
3.1.4 L'heritage des le descriptors
Le mecanisme de creation de processus UNIX possede la propriete de faire heriter au processus
ls les le descriptors du pere. Un programme n'est donc pas oblige d'aecter lui-m^eme des
chiers aux le descriptors sur lesquels il realise des entrees-sorties. Cette aectation peut
^etre realisee par son pere. On peut donc concevoir deux programmes P1 et P2 qui collaborent
de la maniere suivante:
P1
-fd = open("data",O_RDONLY,0)
creation d'un processus pour
executer P2
|
|
|
|
|
|
|
P2
-read(fd,buffer,nboct)
...
close(fd)
3.2 Le shell et les ltres
Nous avons deni un ltre au chapitre 1.4 comme etant un programme qui lit ses donnees sur
l'entree standard (le descriptor 0), ecrit ses resultats sur la sortie standard (le descriptor
1) et produit d'eventuels messages d'erreur sur l'erreur standard (le descriptor 2), selon le
schema suivant:
+-------+
|
| --->
22
sortie standard
(fd 1)
entree standard (fd 0)
---> | prog |
|
| --->
+-------+
erreur standard
(fd 2)
Nous pouvons maintenant preciser qu'un ltre n'aecte pas de chier a ces trois le descriptors, il delegue cette responsabilite au programme qui l'appelle.
Le shell a donc sa propre stategie d'aectation des le descriptors quand il lance un
programme. Si l'utilisateur ne precise rien, le shell transmet au programme appele les le
descriptors 0,1 et 2 aectes au terminal. Pour les cas ou ces aectations par defaut ne
conviennent pas a l'utilisateur, le shell dispose d'un mecanisme permettant de specier les
aectations desirees. Ce mecanisme s'appelle la redirection des entrees-sorties.
3.3 Notations de redirections
Les notations de redirections peuvent apparaitre avant ou apres la commande et dans n'importe
quel ordre. Il est traditionnel de les mettre apres la commande, et si on redirige entree et
sortie, de mettre la redirection de l'entree, puis celle de la sortie, mais ce n'est nullement
obligatoire. A la place de la facon traditionnelle:
cmd < data_in > data_out
on peut ecrire indierement:
< data_in cmd > data_out
< data_in > data_out cmd
cmd > data_out < data_in
Il est possible de rediriger autant de le descriptors d'un programme qu'on le desire:
prog > resu 2> errors 3> fic 4> data
3.4 Redirection et substitutions
Le nom de chier sur lequel porte une redirection subit la substitution de variables et de
commande mais pas la generation de noms de chiers. On peut donc ecrire:
FICHIER=...
cmd > $FICHIER
ou:
cmd > `...`
Mais si on ecrit:
cmd > fic*
quand bien m^eme le modele fic* correspondrait a un seul chier, (par exemple fichier_resultat),
il n'y aurait pas substitution de nom de chier. Cette commande aura pour eet de mettre
le resultat de cmd dans un chier de nom fic*.
23
3.5 Redirection d'un ot d'entree
Deux formes:
< nom-de-chier permet de rediriger l'entree standard d'une commande (le descriptor
0) a partir de nom-de-chier.
chire < nom-de-chier permet de rediriger le le descriptor chire d'une commande a
partir de nom-de-chier.
Dans la seconde forme, attention a ne pas laisser de blanc entre chire et le signe <.
Exemple:
mail serge < lettre
cmd 3< data
Dans le premier exemple, l'entree standard de mail est redirigee vers le chier lettre, dans
le second exemple, le programme cmd (qui est suppose lire sur le le descriptor 3) voit le ot
de donnees associe a ce le descriptor redirige vers le chier data.
3.6 Redirection d'un ot de sortie
Deux formes de base, similiaires aux precedentes:
> nom-de-chier permet de rediriger la sortie standard d'une commande (le descriptor
1) a partir de nom-de-chier.
chire > nom-de-chier permet de rediriger le le descriptor chire d'une commande a
partir de nom-de-chier.
si nom-de-chier existe, son ancien contenu est perdu.
Il existe deux autres formes consistant a remplacer le signe > par le signe >>. Dans ce cas,
si nom-de-chier existe, son contenu n'est pas perdu : le ot redirige va s'ecrire a la n du
chier.
exemples:
cmd
cmd
cmd
cmd
> resu
2>errors
> resu 2>errors
3>fic
Dans le premier cas, la sortie standard est redirigee sur le chier resu et les erreurs sortent
sur le terminal. Dans le second cas, la sortie standard sort sur le terminal, et les erreurs sont
redirigees dans le chier errors. Dans le troisieme cas, la sortie standard ets redirigee vers
le chier resu et les erreurs sont redirigees vers le chier errors. Dans le quatrieme cas, le
programme cmd (qui est suppose ecrire sur le le descriptor 3) voit le ot de donnees associe
a ce le descriptor redirige vers le chier fic.
24
3.7 Redirection vers un le descriptor
Au lieu de rediriger un ot de donnees vers un chier il est possible de le rediriger vers un
autre le descriptor deja ouvert. Ceci se fait par:
>& chire
chire1 >& chire2
<& chire
chire1 <& chire2
Attention a ne pas laisser de blanc entre le signe & et le chire. L'utilisation la plus
courante de cette possibilite est de rediriger la sortie standard et la sortie erreur vers le m^eme
chier. Exemple:
cc -o essai essai.c > log 2>&1
3.8 fermeture d'un ot de donnees
fermeture de l'entree standard
>&- fermeture de la sortie standard
chire >&- fermeture du le descriptor chire
<&
3.9 Redirection d'un ot d'entree sur l'entree du shell
Cette possibilite n'est interessante que dans les chiers de commandes. Supposons que l'on
desire ecrire un chier de commandes qui utilise un editeur pour faire le type de modications
vu au chapitre 1.4. On peut mettre les commandes a l'editeur:
%s/^[^0-9]*//
%s+car.*in+ / +
%s/ seconds//
w
dans un chier que l'on appellera ex.com et ensuite faire ex data < ex.com. Ceci a l'inconvenient
de nous obliger a gerer deux chiers pour un seul programme ; il serait plus agreable de pouvoir mettre les commandes de l'editeur dans le chier de commandes lui-m^eme. Cela est
possible en redirigeant l'entree standard a l'aide de la convention << marque-de-n Exemple:
$ cat cree_expr
#!/bin/sh
# shell
ex <<FIN
r data
%s/^[^0-9]*//
%s+car.*in+ / +
25
%s/ seconds//
w
q
FIN
$
La cha^ne choisie comme marque de n (ici FIN) est completement arbitraire.
Dans les lignes qui sont ainsi passees au programme, le shell continue a realiser la substitution de variables ainsi que la substitution de commandes. D'autre part, le caractere \ rend
litteral le caractere qui le suit dans le cas ou ce caractere est l'un quelconque de \$`.
On peut proter de cela pour parametrer, dans l'exemple precedent, le nom du chier
dans lequel se font les substitutions.
$ cat CREE_EXPR
#!/bin/sh
# shell
ex <<FIN
r $1
%s/^[^0-9]*//
%s+car.*in+ / +
%s/ seconds//
w
q
FIN
$ chmod +x CREE_EXPR
$ CREE_EXPR data
Il peut arriver que les substitutions de variables et de commandes que le shell realise entre
le << marque-de-n et marque-de-n soit genantes. Il y a un moyen d'inhiber ces substitutions:
il sut que l'un quelconque des caracteres composant le mot marque-de-n soit quote. Si la
marque-de-n est le mot FIN on peut donc utiliser indierement \FIN F\IN FI\N ou 'FIN'.
Plut^ot qu'utiliser anarchiquement n'importe quelle notation, on utilisera de preference la
derniere qui est la plus lisible.
Voici un chier de commandes qui met en evidence l'inhibition des mecanismes de substitution:
$ cat ESSAI
#!/bin/sh
V=hello!
echo premier cas
cat > resu <<FIN
$V
`date`
FIN
cat resu
echo deuxieme cas
cat > resu <<'FIN'
$V
26
`date`
FIN
cat resu
Et voici le resultat:
$ ESSAI
premier cas
hello!
Mon Oct 21 12:44:07 MET 1991
deuxieme cas
$V
`date`
$
3.9.1 Applications classiques de ce mecanisme
Il y a deux applications classiques a ce mecanisme: la creation de chier d'archive, et la
creation de chier avec substitution de mots.
Creation de chier archive
Il est parfois interessant de remplacer un ensemble de petits chiers par un seul chier
d'archive: soit pour la conservation, et le but est le gain de place disque, soit pour la distribution de logiciel, et le but est la simplicite de la distribution. Il existe pour resoudre ce
probleme deux commandes shar et unshar. Leur but est de creer ou d'exploiter des chiers
qui ont la structure suivante:
#!/bin/sh
cat > fichier1 <<'FIN-DE-FICHIER'
ligne 1 de fichier 1
ligne 2 de fichier 1
FIN-DE-FICHIER
cat > fichier2 <<'FIN-DE-FICHIER'
ligne 1 de fichier 2
ligne 2 de fichier 2
FIN-DE-FICHIER
Quand on execute ce chier de commande, il cree fichier1 et fichier2.
Creation de chier parametre
Il arrive parfois qu'a partir d'un chier modele on ait a creer un chier parametre selon les
valeurs de certaines variables. Cela peut se faire en exploitant le mecanisme de substitution
de variable realise lors d'une redirection d'entree. Voici un exemple de modele de lettre:
#!/bin/sh
# PERSONNE peut valoir 'Monsieur' ou 'Madame'
PERSONNE=Monsieur
# SENTIMENT peut valoir 'le regret' ou 'la joie'
27
SENTIMENT='le regret'
# AVOIR peut valoir 'avez' ou "n'avez pas"
AVOIR="n'avez pas"
cat > lettre <<FIN-DE-FICHIER
$PERSONNE,
J'ai $SENTIMENT de vous annoncer que vous $AVOIR reussi votre examen.
Veuillez agreer, ...
FIN-DE-FICHIER
3.10 Le pseudo-peripherique /dev/null
Le peudo-peripherique /dev/null agit comme une source vide pour des lectures, et comme
un puits sans fond pour des ecritures. En d'autres termes, un programme lisant /dev/null
recevra immediatement une indication de n-de-chier, et toutes les ecritures faites dans
/dev/null seront perdues.
Exemple d'utilisation de /dev/null en sortie: on veut juste tester l'existence d'une cha^ne
de caractere dans un chier avec grep, sans s'interesser a la ligne elle-m^eme si elle existe:
if grep chaine fichier > /dev/null
then
echo la chaine existe
else
echo "la chaine n'existe pas"
fi
Exemple d'utilisation de /dev/null en entree:
classiques de creer un chier de taille nulle.
cp /dev/null fichier
est une des manieres
3.11 Redirection sans commande!
Bien qu'il paraisse aberrant de vouloir rediriger les entrees-sorties d'une commande qui n'exite
pas, le shell permet que l'on fasse:
> fichier
ceci a pour eet de creer un chier de taille nulle si il n'existait pas, ou de le tronquer a une
taille nulle si il existait deja.
On peut egalement ecrire:
< fichier
ceci a pour eet de tester l'existence et le droit de lecture sur le chier fichier.
Voici un exemple d'interaction dans un repertoire comportant un chier sh.info et pas
de chier qqq:
$ < sh.info
$ echo $?
0
$ < qqq
28
qqq: cannot open
$ echo $?
1
$
Cette possibilite fait double emploi avec test
-r fichier
(Voir chapitre 7.4).
3.12 Entrees-sorties et chier de commandes
Nous avons vu qu'un chier de commandes est execute par une nouvelle instance du shell. Ce
shell lit les commandes et les execute. L'ensemble des entrees standard des commandes ainsi
executees forme l'entree standard du chier de commandes, et l'ensemble des sorties standard
des commandes forme la sortie standard du chier de commandes. Ceci a pour consequence
que l'on peut rediriger les entrees-sorties d'un chier de commandes exactement comme celles
d'une commande.
Exemple: creons un chier de commandes qui substitue dans son entree standard les
occurrences de son premier parametre par son second parametre:
$ cat SUBS
#!/bin/sh
sed "s/$1/$2/"
$
Maintenant, executons-le:
cat data
bernard
jean
serge
$ SUBS serge pierre < data
bernard
jean
pierre
$ SUBS serge pierre < data > resu
$
De la m^eme maniere, on peut creer un pipe-line dont l'un des composants est un chier de
commandes. On voit donc que du point de vue des entrees-sorties, les chiers de commandes
se comportent comme les programmes executables.
29
Chapter 4
Les variables
4.1 Les noms des variables
Les noms des variables peuvent ^etre composes:
soit d'une suite de lettres, de chires et du caractere _.
soit d'un chire
soit de l'un quelconque des caracteres * @ # ? - $ !.
Le premier cas correspond au variables creees par l'utilisateur, le deuxieme cas correspond
aux parametres des chier de commandes, le troisiseme cas correspond a un ensemble de
variables gerees par le shell.
4.2 Declaration et types des variables
Il n'est pas necessaire de declarer une variable avant de l'utiliser, comme on est oblige de le
faire dans les langages de programmation classique. Les objets possedes par les variables sont
d'un seul \type" : la cha^ne de caracteres.
4.3 Aectation d'une valeur a une variable
4.3.1 La syntaxe
La syntaxe d'une aectation est la suivante:
nom-de-variable = cha^ne-de-caracteres Exemples
$ V1=1
$ V2=2
$
Attention aucun blanc n'est admissible autour du signe =:
$ V1= a
a: not found
$ V1 =a
V1: not found
$
30
4.3.2 Aectation d'une cha^ne vide
On peut aecter une cha^ne vide a une variable de 3 manieres dierentes:
$ V1=
$ V2=''
$ V3=""
$
4.3.3 Aectation et interpretation des blancs
Si la cha^ne-de-caracteres a aecter a la variable comporte des blancs, il faut en faire un seul
mot a l'aide des quotes.
$ MESSAGE='Bonjour a tous'
$
Les caracteres \blancs" sont par defaut l'espace, la tabulation et le line-feed, on peut donc
aecter une cha^ne formee de plusieurs lignes.
$ MESSAGE='Bonjour a tous
--------------'
$echo $MESSAGE
Bonjour a tous
-------------$
4.3.4 Aectation et substitutions
Dans la cha^ne qui est aectee a la variable, le shell realise la substitution de variable et la
substitution de commandes, mais pas la substitution de noms de chiers.
$ DATE=`date`
$ PERSONNES=$USER
$ FICHIERS=*
La variable DATE va memoriser la date courante, la variable PERSONNE va recevoir la valeur de
la variable USER, mais la variable FICHIER ne va pas recevoir comme valeur la liste des noms
des chiers, mais le caractere *.
4.4 Toutes les techniques de substitution
Il y a au total 6 variantes a la substitution de variables:
$ variable
substitue la valeur de variable
${variable}
substitue la valeur de variable
${variable - mot} si variable a une valeur substituer cette valeur sinon substituer mot
${variable = mot} si variable n'a pas de valeur y aecter mot ensuite substituer mot
${variable ? mot} si variable a une valeur substituer cette valeur sinon imprimer mot et sortir du shell
${variable + mot} si variable a une valeur substituer cette valeur sinon substituer le vide
31
Il est licite de demander la substitution d'une variable a laquelle aucune valeur n'a ete
aectee: la substitution rendra une cha^ne vide. Si ce comportement par defaut n'est pas
satisfaisant, on peut positionner l'option -u a l'aide de la commande interne set (Voir chapitre
6.13).
$ echo :$toto:
::
$ set -u
$ echo :$toto:
toto: parameter not set
$
4.5 Substitution de variables et interpretation des blancs
Le shell procede d'abord a la sunstitution de variables et ensuite a l'interpretation des blancs
(le decoupage en mots). Ceci a pour consequence qu'il n'est pas necessaire que la valeur d'une
variable constitue un parametre entier de commande. Le texte resultant d'une substitution
de commande peut constituer une fraction d'un parametre de commande.
FROM=bernard
TO=jean
sed s/$FROM/$TO/ data
4.6 Substitution de variables et mecanisme de quote
4.6.1 Premier probleme
Supposons que nous gerions un annuaire telephoqnique sous la forme d'un chier dont les
lignes ont la structure suivante:
Jacques Eudes 9056
Serge Rouveyrol 4567
on a cree un chier de commandes notel pour rechercher le numero de telephone de quelqu'un:
$ cat notel
#!/bin/sh
grep -i $1 $HOME/lib/annuaire
$ notel serge
Serge Rouveyrol 4567
$
Essayons manintenant de l'utiliser en lui passant en parametre un nom complet. Comme on
a bien compris ce qui est explique au chapitre 1.2.2, on entoure le nom par des ':
$ notel 'serge rouveyrol'
rouveyrol: No such file or directory
annuaire:Serge Rouveyrol 4567
32
On est tombe precisement sur le probleme que l'on cherchait a eviter. Il faut savoir que
le shell procede a la substitution de variables et ensuite a l'interpretation des blancs. La
cha^ne serge rouveyrol a bien ete passee a notel comme un seul parametre, mais lors du
traitement de la commande grep, le shell a remplace $1 par sa valeur et a ensuite decoupe la
ligne en param`tres, passant ainsi serge et rouveyrol comme deux parametres a grep.
Pour resoudre le probleme, il faut que dans le chier de commandes, $1 soit pris comme
un seul parametre de grep. Il faut donc ecrire:
grep -i "$1" $HOME/lib/annuaire
4.6.2 Second probleme
Supposons que nous ecrivions un chier de commandes qui pose une question a l'utilisateur
et teste la reponse. On a ecrit:
echo "Voulez vous continuer ? [non]"
read $reponse
if [ $reponse = oui ]
then
...
fi
On pose une question a l'utilisateur qui peut repondre par oui, non ou retour chariot. Le non
entre crochet signie que si l'utilisateur ne repond rien, (il tape simplement retour chariot), la
reponse sera consideree comme etant non. Ce chier de commandes fonctionne correctement
si on repond oui ou non, mais on a le message d'erreur:
test: argument expected
si on repond par retour chariot. En eet, dans ce cas la variable reponse a pour valeur la
cha^ne vide, et seulement deux parametres sont passes a test au lieu de trois. Pour resoudre
le probleme, il faut obliger le shell a passer $reponse en parametre m^eme si il est vide. Se
rappelant ce qui a ete dit au chapitre ?? au sujet des parametres nuls, on ecrira:
if [ "$reponse" = oui ]
et le probleme sera resolu.
4.7 La commande interne set et variables
La commande interne set peut ^etre utilisee de plusieurs manieres dierentes. Elle peut servir
a lister les variables connues du shell a un instant donne. Elle permet egalement d'aecter
des valeurs aux variables 1, 2, ...
4.7.1 Lister les variables
La commande set sans parametre permet d'obtenir une liste classee par ordre alphabetique
de l'ensemble des variables avec leurs valeurs.
33
4.7.2 Aectation de valeur aux variable 1 2 ...
La commande interne set permet d'aecter ses parametres aux variables 1, 2 etc...
Exemple:
$ set bonjour a tous
$ echo $1
bonjour
$ echo $2
a
$ echo $3
tous
$
Cette possibite est interessante pour decouper en mots le contenu d'une variable. Voici
un chier de commandes qui extrait la deuxieme colonne d'un chier suppose contenir une
information organisee en colonnes:
while read ligne
do
set $ligne
echo $2
done
Malheureusement, set est un fourre-tout incroyable, il y a une autre utilisation possible:
positionner des options du shell. On peut ecrire par exemple, set -x pour que toute commande soit imprimee avant d'^etre executee. Cette option est parfois utile pour mettre au
point des chiers de commandes.
Mais dans l'utilsation qu'on en fait ici, si par malheur dans le ot d'entree il y a une
ligne qui commence par le caractere -, l'execution de set $ligne va resulter en un message
d'erreur du shell.
Il y a un moyen d'eviter ce probleme, mais ce n'est helas pas le m^eme selon qu'on a un
shell BSD ou SystemV. En BSD, il faut ecrire:
set - $ligne
et en System V:
set -- $ligne
ceci va prevenir set qu'il ne faut pas interpreter le reste de ses arguments comme des
options, mais comme des mots a aecter a 1, 2, ...
4.8 La commande interne readonly
Si on desire proteger des variables de toute aectation ulterieure, on peut les declarer en
lecture seulement avec la commande interne readonly. Invoquer readonly sans parametre
permet d'obtenir la liste de toutes les variables en lecture seulement. Exemple:
34
$ V1=1 V2=2
$ readonly V1 V2
$ V1=3
V1: is read only
$ readonly
readonly V1
readonly V2
$
4.9 Les variables aectees par le shell
Les variables aectees automatiquement par le shell sont les suivantes:
#
nombre de parametres d'un chier de commandes
options courantes du shell
?
valeur retournee par la derniere commande executee
$
numero de processus du shell
!
numero de processus de la derniere commande executee en arriere plan
0
le nom du chier de commandes
0 1...9 param
etres d'un chier de commandes ou aectes par set
*
l'ensemble des parametres d'un chier de commandes
@
l'ensemble des parametres d'un chier de commandes chacun etant protege par "
Quelques commentaires:
1. La variable # est pratique pour verier la validite de l'appel d'un chier de commandes.
On donne en exemple le debut d'un chier de commandes qui verie qu'on lui passe
bien deux parametres.
#!/bin/sh
if [ $# -ne 2 ]
then
echo "Il faut les parametres ... et ..."
exit 1
fi
On fera attention au fait que # contient le nombre de parametres, alors qu'en langage
C, dans main(arg\c{c}argv), argc contient le nombre de parametres + 1.
2. La variable $ est tres pratique pour creer des noms de chiers temporaires dont on
soit s^ur de l'unicite. On pourra ecrire par exemple commande > /tmp/gestion.$$. Si
plusieurs utilisateurs executent le chier de commandes en m^eme temps, on est s^ur qu'il
n'y aura pas de collision entre les noms des chiers temporaires.
3. La variable * est tres pratique pour referencer la liste des parametres sans se preoccuper
de leur nombre. Supposons que l'on cree une commande LPRTEX qui a pour but d'appeler
lpr avec l'argument -d On pourra ecrire:
$ cat LPRTEX
lpr -d $*
35
$ LPRTEX fic1 fic2 fic3
$
La dierence entre * et @ est subtile:
$*
vaut $1 $2 $3 ...
"$*"
vaut " $1 $2 $3 ... "
$@
vaut $1 $2 $3 ...
"$@"
vaut "$1" "$2" "$3" ...
Le chier de commandes suivant et son execution feront comprendre la dierence:
$ cat printparams
#!/bin/sh
echo "*** phase 1 ***"
for i in $*
do
echo $i
done
echo "*** phase 2 ***"
for i in "$*"
do
echo $i
done
echo "*** phase 3 ***"
for i in $@
do
echo $i
done
echo "*** phase 4 ***"
for i in "$@"
do
echo $i
done
$ printparams a 'b c'
*** phase 1 ***
a
b
c
*** phase 2 ***
a b c
*** phase 3 ***
a
36
b
c
*** phase 4 ***
a
b c
$
4.10 La commande interne shift
La commande interne shift a pour eet d'aecter la valeur de $2 a $1, la valeur de $3 a $2,
etc... et d'aecter la valeur du dixieme parametre (qui jusque la etait inaccessible) a $9. De
surcro^t, shift met a jour la variable $# en diminuant sa valeur de 1. La commande shift
permet donc d'acceder aux parametres au dela du neuvieme. Exemple:
#!/bin/sh
# recuperation de 11 parametres
P1=$1 P2=$2 P3=$3 P4=$4 P5=$5 P6=$6 P7=$7 P8=$8 P9=$9
shift
P10=$9
shift
P11=$9
La commande interne shift est egalement agreable pour traiter les parametres optionnels
d'un chier de commandes. Soit le chier de commandes cmd que l'on peut appeler de deux
manieres dierentes: soit cmd chier, soit cmd -a cher. On pourra analyser les parametres
de la maniere suivante:
#!/bin/sh
OPTION=
if [ $# -eq 0 ]
then
echo "Usage: cmd [-a] fichier"
exit 1
fi
if [ $1 = -a ]
then
OPTION=a
shift
fi
FICHIER=$1
4.11 Les variables formant l'environnement
4.11.1 Rappel sur l'execution de programmes UNIX
L'appel systeme permettant de lancer l'execution d'un programme binaire contenu dans un
chier est execve. Cet appel permet de passer au programme a executer non seulement
37
des parametres, mais egalement un ensemble de couples (noms-de-variable,valeur) que l'on
appelle l'environnement du programme. Un couple (nom-de-variable,valeur) est realise sous
la forme d'une chaine de caracteres composee de nom-de-variable suivi du signe = suivi de la
valeur.
L'interface de execve est le suivant:
void
char
char
char
execve(name,argv,envp)
*name;
*argv[];
*envp[];
est le nom du chier contenant le programme a executer. argv est un tableau de
pointeurs vers les parametres. env est un tableau de pointeurs vers les variables.
Un programme qui desire recuperer son environnement doit ^etre programme de la facon
suivante:
name
main(argc,argv,envp)
int argc;
char *argv[];
char *envp[];
On remarque que l'interface prevoit d'indiquer le nombre d'elements du tablau argv : il s'agit
de la variable argc. Par contre, il ne prevoit pas d'indiquer le nombre d'elements du tableau
envp. La n de ce tableau est indiqu
ee par un element a NULL.
Voici un programme qui imprime son environnement d'execution:
main(argc,argv,envp)
int argc;
char *argv[];
char *envp[];
{
int i = 0;
char **p = envp;
while (*p != NULL)
printf("variable # %d: %s\n",i++,*p++);
}
Et voici un resultat de son execution:
variable
variable
variable
variable
variable
variable
variable
variable
variable
#
#
#
#
#
#
#
#
#
0:
1:
2:
3:
4:
5:
6:
7:
8:
HOME=/users/bernard
PATH=/users/bernard/bin:/usr/ucb:/bin:/usr/bin:.
LOGNAME=bernard
SHELL=/bin/sh
MAIL=/usr/spool/mail/bernard
TERM=xterm
TZ=MET-1EET-2;85/02:00:00,267/02:00:00
HOST=ensisps1
VISUAL=/usr/ucb/vi
38
4.11.2 Les variables exportees
C'est le shell qui execute l'appel systeme execve, c'est donc lui qui choisit les variables qui
sont mises dans l'environnement du programme execute. Le shell sh gere deux types de
variables: les variables dites exportees, et les variables dites non exportees. Quand il execute
un execve, le shell met dans l'environnement du programme l'ensemble de ses variables
exportees. Pour exporter une variable, il faut executer la commande interne export en lui
passant en parametre la liste des variables a exporter. Exemple:
VISUAL=/usr/ucb/vi; export VISUAL
A partir de ce moment, tout programme execute aura VISUAL dans son environnement.
Pour lister l'ensemble des variables exportees a un instant donne, il faut executer export
sans argument. ATTENTION: pb.
4.12 Une autre methode pour passer des variables
On peut rajoutter des variables a l'environnement d'un programme en mettant en t^ete de
son invocation des couples nom = valeur. Ces variables seront mises dans l'environnement
du programme execute et ne seront pas connues du shell courant. Prenons un exemple. Le
programme epelle est un vericateur orthographique qui utilise un dictionnaire qui lui est
propre, plus eventuellement un dictionnaire personnel de l'utilisateur. Si l'utilisateur a un tel
dictionnaire, il doit positionner la variable DICOPLUS avec le nom du chier dictionnaire. On
peut donc appeler le vericateur de la maniere suivante:
DICOPLUS=$HOME/lib/dico
epelle document.tex
4.13 Gestion des variables
Le shell interactif de l'utilisateur a des variables. Quand un chier de commandes est execute,
il est execute par une autre instanciation du shell, qui a elle aussi des variables. Ce chier
de commandes peut eventuellement appeler un autre chier de commandes , execute par une
autre instance du shell qui aura elle aussi des variables etc... Au cours de l'execution d'un
chier de commandes on a donc un ensemble de shells qui se sont appeles mutuellement,
chacun ayant des variables. Dans ce chapitre nous allons nous interesser a la facon dont ces
variables sont gerees.
Regle1
Toutes les variables sont locales a un shell: qu'elles soient exportees ou non, elles ne peuvent
pas ^etre modiees par un sous-shell. Exemple:
$ cat setxy
#!/bin/sh
x=10
y=20
$ x=1
$ y=2 ; export y
39
$ setxy
$echo $x $y
1 2
$
Explication: dans le shell qui a execute le chier de commandes il y a eu instanciation d'une
variable x qui a recu la valeur 2. L'existence de cette variable a disparue quand le shell s'est
termine.
Regle2
Les variables exportees sont instanciees dans tous les sous-shells avec leur valeur. Exemple:
$ cat printxy
#!/bin/sh
echo "variables de printxy: x = $x y = $y"
printxy2
$ cat printxy2
#!/bin/sh
echo "variables de printxy2: x = $x y = $y"
$ x=1 ; export x
$ y=2 ; export y
$ printxy
variables de printxy: x = 1 y = 2
variables de printxy2: x = 1 y = 2
$
Regle3
Les variables exportees sont instanciees avec la valeur qu'elles ont dans le dernier shell qui les
exporte.
Modions printxy pour lui faire modier les valeur de x et y et exporter seulement y.
$ cat printxy
#!/bin/sh
echo "variables de printxy: x = $x y = $y"
x=10
y=20 ; export y
printxy2
$ cat printxy2
#!/bin/sh
echo "variables de printxy2: x = $x y = $y"
$ x=1; export x
$ y=2 ; export y
$ printxy
variables de printxy: x = 1 y = 2
variables de printxy2: x = 1 y = 20
40
$
4.14 Les variables utilisees par le shell
Le shell utilise un certain nombre de variables exactement comme n'importe quel programme
peut le faire, c'est a dire pour modier son comportement en fonction de la valeur de ces
variables.
4.14.1 Les variables PS1 et PS2
Les variables PS1 et PS2 ont pour valeur les cha^nes de caracteres utilisees respectivement en
temps que prompt primaire et prompt secondaire par le shell lorsqu'il est utilise de maniere
interactive. Ces deux variables ont comme valeur par defaut $espace et >espace. Le prompt
secondaire est ache par le shell en debut de chaque ligne lorsque l'utilisateur est en train de
taper une commande tenant sur plusieurs lignes.
Exemple d'interaction ou apparait PS2:
$ for fichier in texinfo*
> do
> echo $fichier
> done
texinfo
texinfo-1
texinfo-2
texinfo-3
texinfo-4
texinfo.texinfo
$
Les variables PS1 et
exemple:
PS2
peuvent ^etre modiees comme n'importe quelle variable. Par
$ echo hello
hello
$ PS1="j'ecoute: "
j'ecoute: echo hello
hello
j'ecoute:
4.14.2 La variable HOME
Cette variable est positionnee par le programme login. La valeur qui lui est donnee est celle
du champ repertoire d'origine qui se trouve dans le chier /etc/passwd. On rappelle que ce
chier contient des lignes ayant la structure suivante:
serge:Kk43cgXNNuYSo:40:226:Serge Rouveyrol,113B,4879,:/users/serge:/bin/sh
Chaque ligne est formees de 7 champs separes par des : (deux points). L'avant dernier champ
est le repertoire d'origine de l'utilisateur.
41
La commande cd (change directory) est une commande interne du shell. Quand on l'utilise
sans lui donner de parametre, le shell l'interprete comme signiant cd repertoire-d'origine. Il
utilise alors la valeur de HOME pour satisfaire cette requ^ete.
4.14.3 La variable PATH
La variable PATH est elle aussi aectee par le programme login avant d'appeler le shell. Nous
avons vu (chapitre 2.2) a quoi elle servait.
4.14.4 La variable IFS
Le nom IFS siginie \Internal Field Separator". Cette variable a pour valeur l'ensemble des
caracteres a considerer comme des blancs lors du decoupage d'une ligne de commande en
mots. Par defaut cette variable contient les 3 caracteres blanc, tabulation et line-feed. Pour
voir la valeur de cette variable, echo sur le terminal n'est pas susant (elle ne contient que
des caracteres \blancs").
$ echo $IFS
$ echo "$IFS" > ifs
$ od -x ifs
0000000 2009 0a0a
0000004
$
Blanc, tabulation et line-feed ont respectivement comme valeur hexadecimale 20, 09 et 0a. Le
dernier 0a est le line-feed que le shell imprime pour terminer echo.
Dans les chier de commandes , il est parfois utile de changer la valeur de IFS en conjonction avec la commande interne set. On donne ci-dessous un exemple ou l'on donne a IFS la
valeur : (deux points) pour que la commande set decoupe une ligne de /etc/passwd en ses
dierents champs.
$ SERGE=`grep '^serge' /etc/passwd`
$ echo $SERGE
serge:Kk43cgXNNuYSo:40:226:Serge Rouveyrol,113B,4879,:/users/serge:/bin/sh
$ IFS=:
$ set $SERGE
$ echo $1
serge
$ echo $2
Kk43cgXNNuYSo
$ echo $3
40
$
4.15 Operations sur les variables
Dans un chier de commandes on a parfois besoin de realiser certaines operations sur les
valeurs des variables. Le shell ne contient que trois mecanismes permettant de realiser des
42
operations sur les variables:
1. la commande interne set permet de decouper une cha^ne de caracteres en \mots". Le
caractere servant de separateur de mots peut ^etre parametre par la variable IFS.
2. la structure case permet de tester si la valeur d'une variable est conforme a un modele.
3. la substitution de variable permet de realiser la concatenation :
listefic="$listefic $fic"
Si on a a realiser un traitement qui ne rentre pas dans l'un des cas precedents, il faut le
faire avec les commandes.
Supposons qu'une variable FICHIER contienne un nom de chier se terminant en .c et que
nous voulions remplacer cette terminaison par .o. Cela se fera en soumettant la valeur de
FICHIER a l'appel suivant de sed : sed 's/\.c$/.o/'.
SOURCE=toto.c
OBJET=`echo $FICHIER | sed 's/\.c$/.o/'`
On voit qu'on a resolu le probleme par un combinaison des mecanismes de substitution de
commande, substitution de variable, pipe et quote (pour que le $ dans la commande sed soit
pris de maniere litterale).
La diversite des commandes UNIX est enorme, mais pour realiser des traitements sur les
variables, les plus interessantes sont sans doute:
pour sa capacite de substitution.
awk pour sa capacit
e a traiter les champs d'une cha^ne de caracteres.
cut pour sa capacit
e a couper selon des numeros de colonne.
tr pour sa capacit
e de transformation d'un caractere par un autre.
expr pour sa capacit
e de calculs arithmetiques.
wc pour sa capacit
e de comptage.
sed
43
Chapter 5
Les structures de contr^ole
5.1 Rappel sur les codes de retour de programmes UNIX
Le noyau UNIX a prevu qu'un programme puisse, apres son execution, transmettre une valeur
a celui qui l'a lance. En derniere instruction, un programme execute exit(n), ou n est la
valeur a transmettre, et l'appelant execute wait(&status), ou status est une variable dans
laquelle le noyau UNIX met la valeur transmise.
Ces valeurs ainsi transmises servent de code de retour des programmes: elles servent
a donner une indication sur la facon dont s'est deroulee l'execution du programme. Par
convention, la valeur 0 signie que l'execution du programme s'est deroulee sans erreur. Une
valeur dierente de zero signie qu'il y a eu une erreur, la valeur etant un code choisi par le
programmeur de l'application.
5.2 La gestion des codes de retour par le shell
5.2.1 Code de retour d'un programme
Quand le shell lance l'execution d'un programme en avant plan, il attend la n de l'execution
par un wait(&status). Il est ainsi prevenu du code de retour du programme. Le shell aecte
ce code de retour a la variable ?, que l'on peut manipuler comme n'importe quelle variable.
Faisons un essai avec la commande grep, qui rend une indication d'erreur quand elle ne trouve
pas la cha^ne qu'on lui demande de rechercher:
$ grep toto /etc/passwd
$ echo $?
1
$ grep serge /etc/passwd
serge:Kk43cgXNNuYSo:40:226:Serge Rouveyrol,113B,4879,:/users/serge:/bin/sh
$ echo $?
0
$
Quand le shell lance l'execution d'un programme en arriere plan, il n'attend pas la n
de l'execution et ne peut donc pas connaitre le code de retour. Dans ce cas, la valeur de la
variable ? reete la maniere dont le lancement en programme d'arriere plan s'est passe:
44
Si le lancement a pu ^etre realise (les chiers de redirection des entrees-sorties existaient
bien, etc...), la variable ? vaut 0.
Si le lancement n'a pu ^etre realise, la variable ? vaut 1.
$ grep toto /etc/passwd &
12275
$ echo $?
0
$ grep toto < /jj
/jj: cannot open
$ echo $?
1
$
5.2.2 Code de retour d'un pipe-line
On rappelle qu'un pipe-line est un ensemble de commandes connectees par des pipes. Par
exemple:
$ grep -i serge
7
$
/etc/passwd | wc -l
Le code de retour d'un pipe-line est le code de retour de la derniere commande du pipe-line.
Pour experimenter, realisons un programme (erreur.c) dont le but est de se terminer en
rendant un code d'erreur passe en parametre par l'utilisateur:
$ cat erreur.c
main(argc,argv)
int argc;
char *argv[];
{
exit(atoi(argv[1]));
}
$ erreur 34 | erreur 73
$ echo $?
73
$
5.2.3 Code de retour d'une sequence de commandes
Le code de retour d'une sequence de commandes est le code de retour de la derniere commande
de la sequence.
$ erreur 34 ; erreur 72 ; erreur 89
$ echo $?
89
$
45
5.3 La structure &&
Deux pipe-lines peuvent ^etre connectes par la structure &&. Sa semantique est la suivante:
si le premier pipe-line rend un code de retour de 0, le second est execute, sinon il n'est pas
execute. Experimentons:
$ erreur 34 && echo hello
$ erreur 0 && echo hello
hello
$
Cette structue est adaptee a l'execution d'un programme conditionnee par la bonne execution
d'un autre programme.
Le code de retour d'une structure && est le code de retour du dernier pipe-line execute.
$ erreur 34 && erreur 18
$ echo $?
34
$ erreur 0 && erreur 18
$ echo $?
18
$
5.4 La structure kk
Deux pipe-lines peuvent ^etre connectes par la structure ||. Sa semantique est la suivante:
si le premier pipe-line rend un code de retour dierent de 0, le second est execute, sinon il
n'est pas execute. Cette structure est bien adaptee a l'emission conditionnelle de messages
d'erreurs. Par exemple:
grep $USER /etc/passwd || echo "$USER" "n'existe pas"
remplace avantageusement:
if grep $USER /etc/passwd
then
:
else
echo "$USER" "n'existe pas"
fi
Le code de retour d'une structure || est le code de retour du dernier pipe-line execute.
5.5 Notion de liste de pipe-lines
La syntaxe des structures de contr^ole qui suivent fait appel a la notion de liste de pipe-line.
Sa denition est la suivante: une liste de pipe-lines est un ensemble de pipe-lines connectes
par ; && || ou line-feed.
Le code de retour d'une liste de pipe-lines est le code de retour du dernier pipe-line execute.
Exemple de liste de pipe-lines:
46
cmd && echo "execution de cmd ok" || echo "erreur a l'execution de cmd"
ou:
sort rawdata > data
lpr data
5.6 La structure for
5.6.1 La syntaxe
Attention a la syntaxe qui est penible: il faut aller a la ligne de la maniere indiquee ci-dessous.
La syntaxe est la suivante:
for nom in ( liste-de-mots )
do liste-de-pipe-lines
done
Dans liste-de-pipe-lines les commandes peuvent ^etre separees par des points virgules ou
par des Retour Chariot.
La partie in ( liste-de-mots ) est optionnelle. Si elle est omise, le shell la remplace par
"$@". La s
emantique de "$@" est expliquee au chapitre 4.9.
Ecriture d'un for sur une seule ligne:
for nom in liste-de-mots ; do liste-de-pipe-lines ; done
5.6.2 La semantique
La structure for itere l'execution de liste-de-pipe-lines. A chaque pas de l'iteration, la variable
nom prend comme valeur le mot suivant de liste-de-mots
5.6.3 Exemples
for fichier in essai1.c essai2.c essai3.c
do
echo je compile $fichier
cc -c $fichier
done
for fichier in *.c; do cc -c $fichier; done
5.7 La structure if
5.7.1 La syntaxe
Il y a plusieurs formes possibles: avec ou sans partie else, partie else combinee avec un if pour
faire un elif (else if).
La syntaxe est la suivante:
if liste-de-pipe-lines
then liste-de-pipe-lines
fi
47
ou:
if liste-de-pipe-lines
then liste-de-pipe-lines
else liste-de-pipe-lines
fi
ou:
if liste-de-pipe-lines
then liste-de-pipe-lines
elif liste-de-pipe-lines
else liste-de-pipe-lines
fi
ecriture d'un if sur une seule ligne:
if expression ; then liste-de-pipe-lines ; fi
if expression ; then liste-de-pipe-lines else ; liste-de-pipe-lines ;
fi
5.7.2 La semantique
La liste-de-pipe-lines apres le if est executee, si elle rend un code de retour nul, la listede-pipe-lines de la partie then est executee, sinon, la liste-de-pipe-lines de la partie else est
executee.
Dans la pratique, la liste-de-pipe-lines apres le if est generalement reduite a une seule
commande, et c'est souvent test.
On remarquera que le if su shell fonctionne a l'inverse de celui du langage C. Pour le
shell, la partie then est executee si la partie condition a rendu une valeur nulle.
5.7.3 Exemples
if [ $langue = "francais" ]
then echo bonjour
else echo hello!
fi
5.8 La structure case
5.8.1 La syntaxe
La syntaxe est la suivante:
case mot in
liste-de-modeles ) liste-de-pipe-lines ;;
liste-de-modeles ) liste-de-pipe-lines ;;
esac
Dans les listes-de-modeles les modeles sont separes par le caractere |
48
5.8.2 La semantique
La semantique des modeles
Les modeles sont les m^emes que ceux qui servent de modeles de noms de chiers. Les
metacaracteres sont * ? [ ] avec la m^eme semantique. Un mot est dit conforme a une
liste-de-modeles si il est conforme a l'un quelconque des modeles de la liste (le caractere | a
donc le sens d'un \ou").
La semantique du case
Le mot est compare successivement a chaque liste-de-modeles. A la premiere liste-de-modeles
pour laquelle le mot correspond, on execute la liste-de-pipe-lines correspondante.
5.8.3 Exemples
case $langue
francais)
anglais)
espagnol)
esac
in
echo Bonjour ;;
echo Hello ;;
echo Buenos Dias ;;
case $param in
0|1|2|3|4|5|6|7|8|9
[0-9]*
[a-zA-Z]*
*
esac
)
)
)
)
echo
echo
echo
echo
$param
$param
$param
$param
est un chiffre ;;
est un nombre ;;
est un nom ;;
de type non prevu ;;
5.9 La structure while
5.9.1 La syntaxe
La syntaxe est la suivante:
while liste-de-pipe-lines
do liste-de-pipe-lines
done
5.9.2 La semantique
La structure while itere:
execution de la liste-de-pipe-lines du while
si celle ci rend un code de retour nul il y a execution de la liste-de-pipe-lines du do,
sinon la boucle se termine.
De la m^eme maniere que pour la structure if, la liste-de-pipe-lines de la partie while est
generalement reduite a une seule commande.
49
5.9.3 Exemples
L'exemple ci-dessous realise une boucle de 10 iterations:
i=1
while test $i -le 10
do
...
i=`expr $i + 1`
done
5.10 La structure until
5.10.1 La syntaxe
La syntaxe est la suivante:
until liste-de-pipe-lines
do liste-de-pipe-lines
done
5.10.2 La semantique
La structure until itere l'execution de la liste-de-pipe-lines du until, si celle ci rend un code
de retour nul il y a execution de la liste-de-pipe-lines du do, sinon la boucle se termine.
De la m^eme maniere que pour la structure if, la liste-de-pipe-lines de la partie until est
generalement reduite a une seule commande.
5.11 La structure sous-shell
5.11.1 La syntaxe
La syntaxe est la suivante:
( liste-de-pipe-lines )
5.11.2 La semantique
La liste-de-pipe-lines est executee par une autre invocation de sh.
5.11.3 Exemples
L'utilite d'une telle structure est de permettre d'agir a l'aide des operateurs pipe, mise dans
l'arriere plan, redirection des entrees-sorties sur une ensemble de commandes, et non pas sur
une seule commande.
Exemple 1: on veut executer en arriere plan deux commandes dont l'ordre d'execution
doit ^etre respecte : la premiere produit un chier necessaire a la seconde.
(sort data -o data_trie; lpr data_trie) &
Exemple 2: on veut piper la sortie de deux commandes dans une autre commande:
50
(echo "je t'envoie ca pour information" ; cat lettre ) | mail serge
Exemple 3: on veut rediriger l'erreur standard de plusieurs commandes a la fois.
(cc -c fic1.c ; cc -c fic2.c ) 2>erreurs
5.12 Plus sur les structures de contr^ole
5.12.1 Break et continue
Il est possible de sortir d'une boucle for, while ou until a l'aide de la commande interne
break. Il est possible d'indiquer un param
etre numerique permettant de sortir de plusieurs
boucles a la fois. Exemple:
while true
do
read ligne
if [ $ligne = stop ]
then
break
else
...
fi
done
5.12.2 Redirection des entrees-sorties
Il est possible de rediriger les entrees-sorties d'une structure conditionnelle (if ou case) ou
de boucle (for, while, until) ou de sous-shell. ex:
for i in fic1 fic2
do
cc -c $i.c
done 2> erreurs
Chaque commande peut avoir ses entrees-sorties redirigees independement:
for i in fic1 fic2
do
echo "Je traite $i" > /dev/tty
cc -c $i.c
done 2> erreurs
5.12.3 Pipe
Il est possible de piper les m^emes structures soit en entree soit en sortie.
ex:
cat noms | while read nom
do
sort $nom -o $nom
done
51
5.12.4 Execution en arriere plan
Il est possible d'executer les structures de contr^ole en arriere plan.
for i in fic1 fic2
do
cc -c $i.c
done &
5.12.5 Attention
Quand on redirige ou que l'on pipe les entrees-sorties ou que l'on met dans l'arriere plan
un telle structure, celle-ci est executee dans un sous-shell. Attention donc si on utilise des
variables. ex:
nbligne=0
grep hello data | while read ligne
do
nbligne=`expr $nbligne + 1`
done
A la n, la variable nbligne vaut toujours 0! Il y a eu incrementation de la variable nbligne
du sous-shell cree pour executer le while puis disparition de cette variable lors de la n du
while qui a entraine la mort du sous-shell.
52
Chapter 6
Les commandes internes
Une ligne soumise au shell est interpretee comme etant la demande d'execution d'une commande. Ces commandes sont generalement des programmes independants du shell comme
par exemple ls ou echo. Le shell reconnait cependant un certain nombre de commandes
comme etant des ordres qui lui sont adresses: on les appelle les commandes internes.
6.1 Pourquoi des commandes internes?
Nous avons deja vu (chapitre 2.6) que le shell lance un nouveau processus pour executer un
programme. Il est donc impossible de modier de cette maniere l'etat du processus qu'est le
shell. En particulier, le repertoire courant fait partie de l'etat d'un processus. Il est impossible
que la commande cd (Change directory) soit une commande externe au shell. Il faut que le
shell interprete lui-m^eme cette commande en executant un appel au noyau UNIX chdir(2).
6.2 La commande commentaire
La commande # sert a indiquer une ligne commentaire dans les chiers de commandes. On
rappelle que la commande what extrait d'un chier toute lignes contenant la chaine magique
@(#). C'est une bonne m
ethode de travail de commencer un chier de commande par quelques
lignes ainsi commentees pour donner la fonction du chier.
#!/bin/sh
#
# @(#) consultation du fond documentaire de la mediatheque
#
6.3 La commande : (deux points)
Cette commande ne fait rien, mais ca ne l'empeche pas d'^etre utile!
if grep $chaine $fichier > /dev/null
then
:
ne rien faire
else
53
echo "Attention $chaine n'exite pas dans $fichier"
exit 1
fi
Ce qu'il y a apres le signe : est ignore, cela peut donc servir de commentaire, mais la commande : n'est pas un commentaire, c'est une commande nulle. En particulier, elle permet de
satisfaire la syntaxe du if, ce que la commande # ne permet pas.
6.4 la commande . (point)
Cette commande a ete traitee au chapitre 2.6.3.
6.5 La commande cd
La syntaxe est: cd nom-de-repertoire
Cette commande demande au shell de prendre comme repertoire courant nom-de-repertoire.
Le nom-de-repertoire est optionnel, quand il est omis on utilise la valeur de la variable HOME
6.6 La commande eval
Le shell procede aux operations suivantes dans l'ordre indique:
1. decoupage en commandes connectees par pipe, redirection des entrees-sorties.
2. substitution de variables
3. substitution de commandes
4. interpretation des blancs
5. generation de noms de chiers.
Cet ordre est generalement conforme a ce que l'on desire. Il arrive cependant que l'on desirerait
un ordre dierent. Supposons que l'on veuille obtenir substitution de commande puis substitution de variables:
$ cat vars
$V1 $V2
$ V1=1
$ V2=2
$ echo `cat vars`
$V1 $V2
$
On voudrait que l'echo nous donne non pas le nom des variables mais leur valeur. La commande interne eval permet de resoudre ce probleme. Sa syntaxe est la suivante: eval
commande
Elle a pour eet de realiser deux fois la suite des 5 operations precedemment citees.
54
$ eval echo `cat vars`
1 2
$
Autre exemple ou on a besoin de realiser deux fois la substitution de variables: on veut
faire echo d'un parametre dont le numero est contenu dans une variable.
$ set bonjour a tous
$ echo $3
tous
$ N=3
$ echo \$$N
$3
$ eval echo \$$N
tous
$
6.7 La commande exec
Nous avons deja vu (chapitre 2.6) que le shell execute les programmes en lancant a chaque fois
un nouveau processus. Il arrive parfois que l'on desire que le processus shell execute lui-m^eme
le programme. Cela revient a remplacer l'execution du shell par l'execution du programme
demande.
6.7.1 Utilisation normale de exec
En utilisation interactive, cela n'a pas de sens d'utiliser exec, car cela revient a tuer le shell
que l'on utilise. Dans un chier de commandes au contraire, on peut utilise exec pour executer
la derniere commande du chier de commandes . Cela economise les ressources de la machine:
au lieu d'y avoir deux processus, il n'y en a qu'un.
6.7.2
exec
et redirection des entrees-sorties
Il est possible de rediriger les entrees-sorties de la commande qui est soumise a exec. Mais on
peut aussi invoquer exec sans commande, simplement en redirigeant les entrees-sorties. Dans
ce cas, exec a pour eet de rediriger les entrees-sorties du shell. Par exemple la commande
interne read lit sur l'entree standard. On peut la faire lire a partir d'un chier en redirigeant
l'entree standard du shell gr^ace a exec. Voici en exemple un chier de commandes qui imprime
la premiere colonne d'un chier dont le nom est passe en parametre.
#!/bin/sh
exec < $1
while read ligne
do
set $ligne
echo $1
done
55
Il est possible d'aecter dans un m^eme chier de commandes les entrees-sorties vers des
chiers dierents a l'aide de plusieurs appels a exec. Si apres redirection, on desire reaecter
l'entree standard au terminal, il sut de faire:
exec < /dev/tty
/dev/tty
est en eet un pseudo-peripherique qui designe le terminal de l'utilisateur.
6.8 La commande exit
La commande interne exit permet de terminer un shell en transmettant un code de retour.
Si exit est invoque avec un parametre, c'est ce parametre qui est pris comme code de retour.
Sinon, le code de retour sera le code de retour de la derniere commande executee.
Clasiquement, les test de validite d'appel d'un chier de commandes sont codes de la
maniere suivante:
#!/bin/sh
if [ $# -ne 2 ]
then
echo "Il faut les parametres ... et ..."
exit 1
fi
Ici, le programmeur a choisi la valeur 1 comme signiant \nombre de parametres incorrect".
6.9 La commande export
Cette commande a ete traitee de maniere exhaustive au chapitre 4.11.2.
6.10 La commande login
Syntaxe: login parametres
Son eet est celui de exec login parametres. Ceci signie que l'on abandonne le shell
courant. Si on desire appeler login sans abandonner son shell courant, il faut faire: /bin/login
parametres. Dans ce cas, lors du logout, on reviendra dans le shell appelant.
6.11 La commande read
Syntaxe: read liste-de-noms
La commande read lit une ligne sur l'entree standard, la decoupe en mots et aecte chaque
mot aux variables de la liste-de-noms. Si la ligne lue comporte plus de mots que la liste-denoms comporte de noms, il aecte au dernier nom l'ensemble des mots restant a aecter.
read rend un code de retour nul sauf sur n de chier. Exemple d'utilisation:
while read c1 c2 c3
do
echo c1 = $c1 c2 = $c2 c3 = $c3
done
56
6.12 La commande readonly
La commande readonly a ete traitee de maniere exhaustive (chapitre 4.8).
6.13 La commande set
La commande set a trois utilisations possibles:
1. Utilisee sans parametre, elle donne la liste alphabetique des variables avec leur valeur.
Ceci a ete vu au chapitre 4.7.1.
2. Elle permet d'aecter se parametres aux variables 1, 2, ... Ceci a ete vu au chapitre
4.7.2.
3. Elle permet egalement de positionner des options du shell.
Les options possibles sont les suivantes:
-e SI le shell n'est pas interactif, stopper a la premiere commande qui rend une erreur.
-k traiter tous les couples nom=valeur, pas seulement en sebut de ligne mais n'importe ou
dans la ligne.
-n lire les commandes mais ne pas les executer. Permet de verier la syntaxe d'un chier
de commandes.
-t terminer le shell apres avoir execute une seule commande.
-u generer une erreur sur reference d'une variable non explicitement initialisee.
-v imprimer les lignes lues par le shell avant de les executer.
-x imprimer les commandes et leurs parametres avant de les executer. Utile pour mettre
au point un chier de commandes.
6.14 La commande shift
La commande shift a ete traitee de maniere exhaustive (chapitre 4.10).
6.15 La commande times
Imprime les temps cumules pour tous les processus lances depuis le debut de la session. Les
temps imprimes sont les temps d'execution en mode utilisateur et temps d'execution en mode
systeme.
$ times
0m0s 0m0s
$ sort data -o data_triees
$ times
0m12s 0m2s
57
$ sort data -o data_triees
$ times
0m25s 0m4s
$
6.16 La commande trap
La commande interne trap permet de specier une commande a executer sur reception de
signaux. Sa syntaxe est la suivante:
trap commande liste-de-signaux
dans laquelle la liste-de-signaux est une liste de numeros correspondant aux signaux geres par
le noyau UNIX. Voici une liste des signaux qu'il peut ^etre interessant de recuperer Dans un
chier de commandes. cette liste est compatible UNIX BSD et System V.
0 exit du shell
1 Hangup
2 Interrupt
3 Quit
15 Software terminaison
6.16.1 Exemple
Voici un chier de commandes dans lequel on recupere le signal \Interrupt".
$ cat recup_intr
#!/bin/sh
trap "echo interruption" 2
while true
do
sleep 10000
echo "je suis reveille"
done
$
Et une activation:
$ recup_intr
interruption
je suis reveille
interruption
je suis reveille
interruption
je suis reveille
A 3 reprises, l'utilisateur a envoye le caractere \intr" (dans ce cas, la touche DEL du terminal):
58
$ stty -a
speed 9600 baud; line = 0;
intr = DEL; quit = ^|; erase = ^h; kill = ^u; eof = ^d; eol = ^`
swtch = ^`
-parenb -parodd cs8 -cstopb hupcl cread -clocal
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -iuclc
ixon -ixany -ixoff -loblk
isig icanon -xcase echo echoe echok -echonl -noflsh
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel
6.16.2 Application typique
L'application typique de la recuperation des signaux est le nettoyage a realiser sur les chiers
temporaires. Dans le cas ou un chier de commandes a besoin de chiers temporaires, il ne
faut pas oublier d'eacer ces chiers en cas d'avortement de l'execution. Comme ce nettoyage
doit aussi se faire sur terminaison normale d'execution, on programme classiquement de la
maniere suivante:
#!/bin/sh
#
TEMPO : fichier temporaire
TEMPO=toto.$$
trap "rm -f $TEMPO" 0 1 2 3 15
....
Petite subtilite: dans le cas de la terminaison sur reception de l'un des signaux 1 2 3 ou
15, la commande rm sera executee deux fois, car en plus il y aura le signal 0 (n du shell).
Ceci explique dans l'exemple, l'utilisation de l'option -f pour eviter le message d'erreur de
rm lorsqu'
a la seconde execution il essaye d'eacer un chier qui n'existe pas.
6.17 La commande umask
6.17.1 umask dans le noyau UNIX
Dans le contexte d'un processus UNIX il existe une variable qui porte le nom de umask.
Cette variable est utilisee lorsque le processus cree un chier. Lors d'une creation de chier,
l'utilisateur specie les permissions qu'il desire aecter a ce chier. Mais les permissions
eectivement allouees au chier sont les permissions demandees auquelles on enleve celles
de umask. Chaque bit a 1 dans umask indique en eet une position a mettre a 0 dans les
permissions du chier. Classiquement, la valeur par defaut de umask est 022 (en octal) de
maniere a ne pas mettre les permissions write au groupe et aux autres.
6.17.2 umask dans le shell
La commande interne umask permet d'aecter une valeur au umask du processus qu'est le
shell. Sa synatxe est la suivante: umask nombre
ou nombre est un nombre exprime en octal. Il faut savoir que lorsque le shell cree un chier
pour redirection d'une sortie, il le cree en utilisant les permissions -rw-rw-rw- Exemple:
59
$ umask 0
$ > t1
$ ls -l t1
-rw-rw-rw$ umask 22
$ > t2
$ ls -l t2
-rw-r--r-$
1 bernard
0 Nov 13 15:03 t1
1 bernard
0 Nov 13 15:04 t2
6.18 La commande wait
La commande interne wait a pour but s'attendre la n d'un processus qui s'execute en arriere
plan. Sa syntaxe est la suivante:
wait num
ero
ou numero est le numero de processus que l'on desire attendre.
60
Chapter 7
La commande test
7.1 Presentation
La commande test permet d'exprimer des predicats sur les cha^nes de caracteres, sur les entiers
et sur les chiers. La valeur de ces predicats peut ensuite ^etre testee dans une structure if,
while ou until. La commande test ne fait pas partie du shell, mais la programmation en
shell en fait un tel usage qu'il est logique de lui consacrer un chapitre. La commande test
reside traditionnelement sous /bin. Le shell en fait un tel usage, qu'il y a un alias qui porte
le nom [ (oui, c'est un chier qui se nomme [)! Ceci peut se voir gr^ace a l'option -i de ls:
$
ls -i /bin/test /bin/[
4208 /bin/[
4208 /bin/test
$
Les deux noms ont m^eme numero de inode, ils reperent donc le m^eme chier.
Ceci permet d'ecrire:
if [ $rep = "oui" ]
then
...
fi
a la place de :
if test $rep = "oui"
then
...
fi
Le shell System V a introduit la commande test en commande interne, mais en restant
compatible avec /bin/test.
7.2 Predicats sur les cha^nes de caracteres
Dans ce qui suit, on notera s1 et s2 deux cha^nes de caracteres. Les operateurs dont on dispose
sont les suivants:
61
s1 = s2
s1 != s2
-n s1
-z s1
vrai si s1 est egal a s2
vrai si s1 est dierent de s2
vrai si s1 est non vide
vrai si s1 est vide
7.3 Predicats sur les entiers
n1 -eq n2
n1 -ne n2
-gt n2
Dans ce qui suit, n1 et n2 sont des nombres decimaux. n1
n1 -ge n2
n1 -lt n2
n1 -le n2
vrai si n1 est egal a n2
vrai si n1 est dierent de n2
vrai si n1 est strictement superieur a n2
vrai si n1 est superieur ou egal a n2
vrai si n1 est strictement inferieur a n2
vrai si n1 est inferieur ou egal a n2
7.4 Predicats sur les chiers
-r
-w
-f
-d
-s
chier
chier
chier
chier
chier
vrai si chier existe et on a le droit read
vrai si chier existe et on a le droit write
vrai si chier existe et n'est pas un repertoire
vrai si chier existe et est un repertoire
vrai si chier existe et a une taille non nulle
7.5 Predicats sur les descripteurs de chiers
-t
fd vrai si fd est un descripteur associe a un terminal
7.6 Combinaison de predicats
!
-a
-o
( )
operateur not booleen
operateur and booleen
operateur or booleen
pour parentheser les sous-expressions
7.7 Les problemes
Attention a bien passer chaque operateur et operande comme un argument a test. Ne pas
ecrire
if [$cmd=end]
mais:
if [ $cmd = end ]
Attention en ce qui concerne les parentheses: elles ont une signication pour le shell, il
faut donc les quoter pour les tranmettre telles quelles a test. ex:
62
if [ $ordre = w -a \( $nb -qt 20 -o $nb -lt 10 \) ]
then
...
fi
63
Chapter 8
La commande expr
La commande expr permet de realiser des calculs arithmetiques, des comparaisons de nombres
entiers et de la reconnaissance de modele. Dans sa capacite de comparaison d'entiers, elle fait
double emploi avec la commande test. Cette commande interprete ses arguments comme
etant une expression, et imprime le resultat sur sa sortie standard. Chaque operande ou
operateur de la liste d'argument doit ^etre passe comme un seul parametre.
Exemple d'utilisation:
$ expr 2 + 3
5
$ expr 2 +3
syntax error
$
Dans ce qui suit, on notera expr une expression formee d'une combinaison d'entiers,
d'operateurs autorises par expr et de parentheses.
8.1 Calculs entiers
expr + expr
expr - expr
On dispose des operateurs suivants: expr * expr
expr / expr
expr % expr
Attention
addition
soustraction
multiplication
division
reste de la division
L'operateur * est un metacaractere pour le shell, il faut le passer a expr de maniere litterale.
$ expr 3 * 4
syntax error
$ expr 3 \* 4
12
$
64
8.2 Comparaisons sur les entiers
expr = expr
expr != expr
> expr
On dispose des operateurs suivants: expr
expr >= expr
expr < expr
expr <= expr
egal
dierent
strictement superieur
superieur ou egal
strictement inferieur
inferieur ou egal
Attention
Tous ces operateurs sauf = et != sont des metacaracteres du shell.
8.3 Les parentheses
On peut parentheser les expressions, mais comme les parentheses sont des metacaracteres
pour le shell, il faut les passer a expr de maniere litterale.
Exemple:
$ expr 3 \* \( 4 + 5 \)
27
$
8.4 Calculs booleens
On dispose des deux operateurs booleens:
expr1 | expr2 rend expr1 si elle n'est pas nulle rend expr2 sinon
expr1 & expr2 rend expr1 si aucune expr n'est nulle rend 0 sinon
Dans ce qui precede, l'expression \^etre nul" peut signier, soit ^etre nul au sens arithmetique,
soit ^etre une cha^ne nulle (vide).
Attention
Ces deux operateurs sont des metacaracteres du shell.
Exemple:
$ expr 1 \& 0
0
$ expr 2 \& 1
2
$ expr 3 \& ''
0
$
8.5 Reconnaissance d'expressions regulieres
La syntaxe est la suivante: expr1 : expr2.
expr2 doit ^etre une expression reguliere du type de celles reconnues par ed.
65
Si expr2 ne comporte pas de sous expression reguliere (parenthesee par \ ( et \ )),
l'operateur : rend comme resultat le nombre de caracteres de expr1 si celle-ci correspond
a l'expression reguliere, et 0 sinon.
Si expr2 comporte une sous expression reguliere, l'operateur : rend la partie de expr1
qui correspond a la sous-expression reguliere, ou le vide si expr1 ne correspond pas a
expr2.
Exemples:
$ expr
4
$ expr
0
$ expr
bbb
$ expr
aaaa : 'a*'
aaa : 'b*'
aaaabbbaa : 'a*\(b*\)a*'
acccaa :
'a*\(b*\)a*'
$
8.6 Utilisation avancee
En combinant plusiurs possibilites de expr, on peut ecrire des constructions tres puissantes.
L'exemple qui est donne dans le manuel de expr est le suivant. Soit une variable FICHIER
dont la valeur est un nom de chier. Ce nom peut ^etre simple (main.c) ou ^etre compose
(../sh/main.c). Supposons que nous voulions extraire le dernier composant de ce nom.
$ FICHIER=main.c
$ expr $FICHIER : '.*/\(.*\)' \| $FICHIER
main.c
$ FICHIER=../sh/main.c
$ expr $FICHIER : '.*/\(.*\)' \| $FICHIER
main.c
$
66
Glossaire
#!/bin/sh
$#
$$
$$0
...
$1$2 $9
$?
&
*
/dev/null
;
?
[
anti-slash
`
|
HOME
PATH
PS1
PS2
A mettre en t^ete d'un chier de commandes pour avoir la certitude qu'il sera execute par /bin/sh quelque soit le shell interactif utilise.
Nombre de parametres d'un chier de commandes.
Numero de processus du shell.
Options courantes su shell.
Dans un chier de commandes, nom du chier.
Parametres d'un chier de commandes reperes par leur position.
Valeur retournee par la derniere commande executee.
Metacaractere provoquant l'execution en arriere plan.
Metacaractere de la generation de noms de chiers.
Source vide pour les entrees et puits pour les sorties.
Metacaractere provoquant l'execution en sequence.
Metacaractere de la generation de noms de chiers.
Metacaractere de la generation de noms de chiers.
(il s'agit du caractere \ ). Metacaractere permettant de rendre
litteral le caractere qui suit (dans certains contextes seulement).
Metacaractere provoquant la substitution de commandes.
Metacaractere provoquant la creation d'un pipe-line.
Variable du shell contenant le nom du repertoire d'origine de
l'utilisateur.
Variable du shell contenant la liste des repertoires dans lesquels
rechercher les commandes a executer.
Variable du shell contenant le prompt principal.
Variable du shell contenant le prompt secondaire.
67
argument
arriere plan
avant plan
background
built-in
BSD
code de retour
commande
commande interne
csh
directory
entree standard
erreur standard
chier de commandes
le descriptor
ot de donnees
ot d'entree
ot de sortie
foreground
Terme anglais pour parametre.
technique d'execution de programme qui consiste pour le shell,
a ne pas attendre la terminaison du programme et a imprimer
le prompt immediatement. Voir aussi avant plan.
technique d'execution de programme qui consiste pour le shell,
a se bloquer jusqu'a la n du programme. Ensuite, le shell
imprime le prompt. Voir aussi arriere plan.
Terme anglais pour arriere plan.
Terme anglais pour commande interne.
Berkeley System Distribution. Nom de la version d'UNIX qui
est distribuee par l'Universite de Californie a Berkeley.
Le code de retour d'un programme est une valeur servant a
transmettre a l'appelant une indication sur la maniere dont le
programme s'est execute.
Une commande est un programme systeme, par opposition a un
programme developpe par un utilisateur.
Un ordre directement interprete par le shell, par opposition aux
commandes qui sont des programmes externes au shell.
Le C shell.
Terme anglais pour repertoire
le descriptor 0 d'un programme. Par defaut, l'entree standard
est aectee au terminal (le clavier).
File desriptor 2 d'un programme. Par defaut, 'erreur standard
est aectee au terminal (l'ecran).
Programme ecrit dans le langage reconnu par l'interpreteur de
commandes.
Peripherique logique d'un programme. Le shell lance l'execution
d'un programme apres avoir aecte ses le descriptor a des
peripherique physiques ou a des chiers. Le terme le descriptor
est du jargon specique a UNIX.
Suite de donnees lues ou ecrites par un programme.
Suite de donnees lues par un programme.
Suite de donnees ecrites par un programme.
Terme anglais pour avant plan.
68
generation de noms de chiers capacite du shell a remplacer un modele par l'ensemble des
noms des chiers qui corrspondent a ce modele
home directory
Terme anglais pour repertoire d'origine.
interpretation des blancs
La phase d'interpretation des blancs est la phase ou le shell
decoupe une commande en mots. Le premier mot sera le nom
du programme appele, les autres mots seront les parametres.
Les caracteres qui sont consideres comme des \blancs" sont contenus dans la variable IFS.
interpreteur de commandes Programme dont la vocation principale est le lancement et
l'execution de programmes.
ksh
Le Korn shell. Developpe par David Korn de ATT Bell Laboratories.
line-feed
Nom du caractere ASCII de code hexadecimal 0a. C'est un
caractere non graphique dont l'eet est de passer a la ligne
suivante. Il est utilise par UNIX en temps que separateur de
ligne dans les chiers texte.
nom de chemin
Un nom de chemin est la designation d'un chier dans l'arborescence
UNIX.
Terme anglais pour nom de chemin.
pipe
Un concept du noyau UNIX. Un pipe est une le d'attente de
caracteres. Sert a la commnunication entre processus.
pipe-line
Ensemble de programmes connectes les uns aux autres, et collaborant selon la technique du travail a la cha^ne: la sortie de
l'un va dans l'entree du suivant via un pipe. Le terme pipe-line
est du jargon specique aux shells UNIX.
processus
Programme en execution
programme binaire
Programme sous forme de binaire executable, par opposition a
un programme sous forme de source ou a un chier de commandes.
prompt
petit message d'invitation a taper. Un programme imprime un
promt pour prevenir l'utilisateur qu'il s'est mis en attente de
lecture.
quote
A strictement parler, il s'agit d'un caractere typographique qui
peut ^etre ' (simple quote), ` (back quote) ou " (double quote).
En LISP le \simple quote" est utilise pour prendre de maniere
litterale ce qui suit. Cet usage a ete repris dans d'autres langages, ce qui a amene une extension du sens du mot quote. Dans
un sens large, \quote" designe tout caractere qui rend litteral
ce qui suit. Dans le shell, les quotes sont ' " \ .
69
repertoire
repertoire courant
repertoire d'origine
set
sh
script
shell
shell script
sortie standard
substitution de variable
substitution de commande
System V
tcsh
variable
Un nud de l'arborescence de chiers UNIX. Un repertoire a
pour but de contenir des chiers et des repertoires.
L'etat d'un processus UNIX contient une reference a un repertoire
dit repertoire courant. Les noms de chemin relatifs sont interpretes relativement au repertoire courant.
Le repertoire qui est pris comme repertoire courant au moment
du login.
commande interne
Le Bourne shell.
Abbreviation pour shell script.
Terme anglais pour interpreteur de commandes.
Terme anglais pour chier de commandes.
le descriptor 1 d'un programme. Par defaut, la sortie standard
est aectee au terminal (l'ecran).
Capacite du shell a remplacer le nom d'une variable par sa
valeur.
Capacite du shell a remplacer une commande par la sortie qu'elle
produit.
Nom de la version d'UNIX qui est distribuee par ATT.
Le ???
Un couple (nom,valeur) gere par le shell. Il existe deux types de
variables les variables exportees et celles qui ne le sont pas. Pour
une introduction voir chapitre 1.8, pour une etude exhaustive
voir chapitre 4.
70
Index
.prole, 18
/dev/null
set, 31, 55
shift, 34, 55
times, 55
trap, 56
umask, 57
wait, 58
commande UNIX
chmod, 10
commentaire, 51
continue, 49
csh, 11
dierences System V et BSD, 4, 15
entree standard, 4
pipe, 7
environnement, 35
erreur standard, 4
eval, 52
exec, 53
exit, 54
export, 36, 54
fermeture d'un ot de donnees, 23
chier
taille nulle, 25
chier de commandes, 9
passage de parametres, 10
chiers temporaires
eacement, 57
nom, 33
le descriptor, 20
ltre, 4
for, 45
generation de noms de chiers, 3, 23
HOME, 39
if, 46
IFS, 3, 39
, 25
appel noyau
close, 20
execve, 35
open, 20
read, 20
write, 20
archive, 25
arriere plan, 7
structure de contr^ole, 50
blancs, 3
break, 49
caractere
espace, 3
case, 47
cd, 39, 52
cha^ne vide, 29
chmod, 10
close, 20
code de retour, 42, 54
commande
login, 39
commande interne
., 18
:, 51
#, 51
break, 49
cd, 39, 52
continue, 49
eval, 52
exec, 53
exit, 54
export, 36, 54
login, 54
read, 54
readonly, 32, 55
71
signaux, 56
sortie standard, 4
pipe, 7
sous-shell, 18, 37, 49, 50
structure de contr^ole
(), 49
arriere plan, 50
case, 47
for, 45
if, 46
pipe, 50
until, 48
while, 48
structures de contr^ole
redirection des entrees-sorties, 50
substitution de commande, 9
substitution de variable, 29
substitution de variables, 23
interpretation des blancs, 3, 16, 39
ksh, 11
login, 54
metacaractere, 11
&, 7
\ , 11
", 2, 11
', 2, 11
*, 3
?, 4
[], 4
|, 7
anti-slash, 11
noyau UNIX, 20
open, 20
tcsh, 11
times, 55
trap, 56
parametre
nul, 16
passage de parametres, 2, 15
PATH, 13, 14, 39
pipe, 7
structure de contr^ole, 50
pipe-line, 7
premier plan, 7
processus, 17
PS1, 38
PS2, 38
umask, 57
unshar, 25
until, 48
variable, 8, 28
aectees par le shell, 32
exportee, 36
gestion par le shell, 37
HOME, 39
IFS, 3, 39
PATH, 13, 14, 39
PS1 et PS2, 38
utilisees par le shell, 38
quote, 16
read, 20, 54
readonly, 32, 55
redirection des entrees-sorties, 4
a partir d'un chier de commandes, 23
d'un ot d'entree, 21
d'un ot de sortie, 22
structures de contr^ole, 50
vers un le descriptor, 22
wait, 58
what, 51
while, 48
write, 20
securite, 14
set, 31, 55
sh, 11
shar, 25
shift, 34, 55
72
Contents
1 Les bases
1.1 Presentation
1.2 L'execution de programme
1.2.1 Programmes et parametres
1.2.2 Parametres formes de plusieurs mots
1.2.3 Interpretation des blancs
1.3 Generation de noms de chiers
1.3.1 Presentation
1.3.2 Le constructeur *
1.3.3 Le constructeur ?
1.3.4 Le constructeur []
1.3.5 Mise en uvre de la generation de noms de chiers
1.4 Redirection des entrees-sorties
1.5 Execution en sequence
1.6 Execution en premier plan ou en arriere plan
1.7 Travail a la cha^ne
1.7.1 Notion de pipe-line
1.8 Les variables
1.9 La substitution de commande
1.10 Les chiers de commandes
1.10.1 Presentation
1.10.2 Passage de parametres
1.10.3 Le shell d'execution
1.11 Le probleme des metacaracteres
2
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
2 L'execution de programme
2.1
2.2
2.3
2.4
2.5
2.6
Rappel sur le systeme de chier UNIX
Recherche du chier a executer
Variable PATH et securite
Variable PATH et environnement BSD ou System V
Passage de parametre a un programme
Programmes et processus
2.6.1 Programmes binaires
2.6.2 Fichier de commandes
2.6.3 Fichier de commandes execute par le shell courant
2.6.4 En resume
14
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
73
2
3
3
3
4
4
4
4
5
5
5
5
7
7
8
9
9
10
10
10
11
12
12
14
14
15
16
16
18
18
19
19
20
3 La redirection des entrees-sorties
3.1 Rappels sur le noyau UNIX
3.1.1 Les primitives d'entrees-sorties
3.1.2 La notion de le descriptor
3.1.3 Peripheriques physiques et chiers
3.1.4 L'heritage des le descriptors
3.2 Le shell et les ltres
3.3 Notations de redirections
3.4 Redirection et substitutions
3.5 Redirection d'un ot d'entree
3.6 Redirection d'un ot de sortie
3.7 Redirection vers un le descriptor
3.8 fermeture d'un ot de donnees
3.9 Redirection d'un ot d'entree sur l'entree du shell
3.9.1 Applications classiques de ce mecanisme
3.10 Le pseudo-peripherique /dev/null
3.11 Redirection sans commande!
3.12 Entrees-sorties et chier de commandes
21
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : :
4 Les variables
4.1 Les noms des variables
4.2 Declaration et types des variables
4.3 Aectation d'une valeur a une variable
4.3.1 La syntaxe
4.3.2 Aectation d'une cha^ne vide
4.3.3 Aectation et interpretation des blancs
4.3.4 Aectation et substitutions
4.4 Toutes les techniques de substitution
4.5 Substitution de variables et interpretation des blancs
4.6 Substitution de variables et mecanisme de quote
4.6.1 Premier probleme
4.6.2 Second probleme
4.7 La commande interne set et variables
4.7.1 Lister les variables
4.7.2 Aectation de valeur aux variable 1 2 ...
4.8 La commande interne readonly
4.9 Les variables aectees par le shell
4.10 La commande interne shift
4.11 Les variables formant l'environnement
4.11.1 Rappel sur l'execution de programmes UNIX
4.11.2 Les variables exportees
4.12 Une autre methode pour passer des variables
4.13 Gestion des variables
4.14 Les variables utilisees par le shell
4.14.1 Les variables PS1 et PS2
4.14.2 La variable HOME
4.14.3 La variable PATH
30
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : :
: : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
74
21
21
22
22
22
22
23
23
24
24
25
25
25
27
28
28
29
30
30
30
30
31
31
31
31
32
32
32
33
33
33
34
34
35
37
37
37
39
39
39
41
41
41
42
4.14.4 La variable IFS
4.15 Operations sur les variables
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
5 Les structures de contr^ole
5.1 Rappel sur les codes de retour de programmes UNIX
5.2 La gestion des codes de retour par le shell
5.2.1 Code de retour d'un programme
5.2.2 Code de retour d'un pipe-line
5.2.3 Code de retour d'une sequence de commandes
5.3 La structure &&
5.4 La structure kk
5.5 Notion de liste de pipe-lines
5.6 La structure for
5.6.1 La syntaxe
5.6.2 La semantique
5.6.3 Exemples
5.7 La structure if
5.7.1 La syntaxe
5.7.2 La semantique
5.7.3 Exemples
5.8 La structure case
5.8.1 La syntaxe
5.8.2 La semantique
5.8.3 Exemples
5.9 La structure while
5.9.1 La syntaxe
5.9.2 La semantique
5.9.3 Exemples
5.10 La structure until
5.10.1 La syntaxe
5.10.2 La semantique
5.11 La structure sous-shell
5.11.1 La syntaxe
5.11.2 La semantique
5.11.3 Exemples
5.12 Plus sur les structures de contr^ole
5.12.1 Break et continue
5.12.2 Redirection des entrees-sorties
5.12.3 Pipe
5.12.4 Execution en arriere plan
5.12.5 Attention
44
: : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
6 Les commandes internes
6.1
6.2
6.3
6.4
Pourquoi des commandes internes?
La commande commentaire
La commande : (deux points)
la commande . (point)
42
43
44
44
44
45
45
46
46
46
47
47
47
47
47
47
48
48
48
48
49
49
49
49
49
50
50
50
50
50
50
50
50
51
51
51
51
52
52
53
: : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
75
53
53
53
54
6.5 La commande cd
6.6 La commande eval
6.7 La commande exec
6.7.1 Utilisation normale de exec
6.7.2 exec et redirection des entrees-sorties
6.8 La commande exit
6.9 La commande export
6.10 La commande login
6.11 La commande read
6.12 La commande readonly
6.13 La commande set
6.14 La commande shift
6.15 La commande times
6.16 La commande trap
6.16.1 Exemple
6.16.2 Application typique
6.17 La commande umask
6.17.1 umask dans le noyau UNIX
6.17.2 umask dans le shell
6.18 La commande wait
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
7 La commande test
7.1
7.2
7.3
7.4
7.5
7.6
7.7
Presentation
Predicats sur les cha^nes de caracteres
Predicats sur les entiers
Predicats sur les chiers
Predicats sur les descripteurs de chiers
Combinaison de predicats
Les problemes
61
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
8 La commande expr
8.1
8.2
8.3
8.4
8.5
8.6
Calculs entiers
Comparaisons sur les entiers
Les parentheses
Calculs booleens
Reconnaissance d'expressions regulieres
Utilisation avancee
61
61
62
62
62
62
62
64
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : :
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
76
54
54
55
55
55
56
56
56
56
57
57
57
57
58
58
59
59
59
59
60
64
65
65
65
65
66
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertising