Bap: Compléments, surtout pour les débutants en programmation
(définition des variables, entrée/sortie, etc.)
This commit is contained in:
parent
329afe7141
commit
d429d8de60
1 changed files with 581 additions and 144 deletions
719
unix/shell.tml
719
unix/shell.tml
|
@ -13,68 +13,165 @@
|
|||
<h2><a name="presentation">Présentation</a></h2>
|
||||
|
||||
<p>
|
||||
Le machin qui interprète les commandes.
|
||||
Le mot <em>shell</em> signifie « coquille » en anglais. Il
|
||||
s'agit du programme que vous utilisez régulièrement à l'ENS, et qui
|
||||
interprète les commandes. Par exemple, vous y tapez <code>pine</code> ou
|
||||
<code>mutt</code>, <code>forum</code>, <code>cc</code>,
|
||||
<code>mozilla</code>, etc.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Mais quel rapport avec une coquille ? Eh bien, dans une coquille
|
||||
vous pouvez mettre de l'eau, pour la porter ensuite à votre
|
||||
bouche ; vous pouvez y mettre du sable avant de le verser dans des
|
||||
bocaux ; en somme, une coquille est un récipient qui permet
|
||||
de manipuler toutes sortes de contenus. Il en va de même du shell. C'est
|
||||
un outil en mode texte qui permet l'exploitation d'un grand nombre de
|
||||
ressources de l'ordinateur.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Cette page vous donnera les rudiments pour exploiter les deux
|
||||
principales fonctionnalités du shell :
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> l'usage interactif, reposant sur les <strong>lignes de
|
||||
commandes</strong> ;</li>
|
||||
<li> la conception de <strong>scripts</strong> (programmes écrits en
|
||||
shell). </li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3><a name="etats">Les deux états du shell</a>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Le shell, comme le normalien, ne connaît que deux états :
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> le travail ;</li>
|
||||
<li> l'inactivité.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Le shell, une fois lancé, est inactif : il attend qu'on lui donne
|
||||
des ordres. Quand on lui en donne un, il l'exécute ; et quand il a
|
||||
terminé, il retourne à son état d'inactivité, en attente d'un nouveau
|
||||
commandement.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Quand le shell est inactif, il affiche une <em>invite</em>
|
||||
(<em>prompt</em> en anglais), qui ressemble à cela :
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span></pre>
|
||||
|
||||
<p>
|
||||
Un curseur, parfois clignotant, indique que le shell attend que vous lui
|
||||
tapiez des instructions.
|
||||
</p>
|
||||
|
||||
<h3><a name="path">Comment le shell trouve-t-il les commandes ?</a>
|
||||
</h3>
|
||||
|
||||
<p> La <a href="#variables">variable</a> <code>PATH</code> contient le
|
||||
chemin d'accès aux commandes. Le shell l'utilise pour trouver les
|
||||
commandes. Il s'agit d'une liste de répertoires séparés par des
|
||||
<code>:</code>. La plupart des commandes sont en fait des programmes,
|
||||
c'est-à-dire des fichiers qu'on trouve dans le système de fichiers. </p>
|
||||
|
||||
<p>
|
||||
Par exemple, quand vous tapez <code>ls</code>, le shell exécute le fichier
|
||||
<code>/bin/ls</code>. Pour trouver ce fichier, il cherche dans le premier
|
||||
répertoire du <code>PATH</code> un fichier qui s'appelle <code>ls</code>.
|
||||
S'il ne trouve pas, il cherche ensuite dans le deuxième répertoire et ainsi
|
||||
de suite.
|
||||
J'ai l'habitude de taper des commandes dans le shell, et je vois qu'il
|
||||
réagit. Mais comment comprend-il ce que je veux faire ?
|
||||
</p>
|
||||
|
||||
<p>
|
||||
S'il ne trouve la commande dans aucun répertoire du <code>PATH</code>, le shell
|
||||
affiche un message d'erreur. Exemple:
|
||||
Prenons un cas simple. Je tape la commande <code>bonjour</code> à
|
||||
l'invite (<em>prompt</em>) du shell. Il va chercher à plusieurs endroits
|
||||
ce que j'entends par là :
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li> d'abord, il va se demander si <code>bonjour</code> n'est pas une de
|
||||
ses commandes intégrées ; si c'est le cas, il l'exécute
|
||||
directement, sinon il passe à l'étape suivante ;</li>
|
||||
<li> ensuite, il va lire le contenu d'une variable, qui s'appelle
|
||||
<code>PATH</code>, et qui indique le « chemin » où trouver les
|
||||
commandes que l'on appelle. Par exemple, si la variable PATH contient
|
||||
les répertoires :
|
||||
<ul>
|
||||
<li> <code>/usr/bin</code> </li>
|
||||
<li> <code>/bin</code> et </li>
|
||||
<li> <code>/home/toto/bin</code>,</li>
|
||||
</ul>
|
||||
alors le shell va chercher successivement les commandes :
|
||||
<ul>
|
||||
<li> <code>/usr/bin/bonjour</code>,</li>
|
||||
<li> <code>/bin/bonjour</code> et </li>
|
||||
<li> <code>/home/toto/bin/bonjour</code> ;</li>
|
||||
</ul></li>
|
||||
<li> enfin, s'il ne trouve la commande dans aucun des répertoires
|
||||
référencés par le <code>PATH</code>, il va renvoyer un message d'erreur
|
||||
en disant que désolé, il ne voit pas ce que l'on entend par
|
||||
<code>bonjour</code>. Exemple :
|
||||
|
||||
<pre>
|
||||
<span class="prompt">chaland ~ $</span> bonjour
|
||||
bonjour: Command not found</pre> </li>
|
||||
</ol>
|
||||
|
||||
<p> La <a href="#variables">variable</a> <code>PATH</code> consiste en
|
||||
une liste de répertoires séparés par des
|
||||
« <code>:</code> ». Si vous voulez voir à quoi ressemble votre
|
||||
PATH, tapez :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<span class="prompt">chaland ~ $</span> sl
|
||||
sl: Command not found</pre>
|
||||
<span class="prompt">chaland ~ $</span> echo $PATH</pre>
|
||||
|
||||
|
||||
|
||||
<h3><a name="builtins">Commandes internes</a></h3>
|
||||
|
||||
<p>
|
||||
Certaines commandes du shell ne sont pas des programmes mais des commandes
|
||||
<em>internes</em> (<em>builtins functions</em>). Elles sont directement
|
||||
reconnues et exécutées par le shell. Un exemple de commande interne est
|
||||
<code>cd</code>. C'est le répertoire courant du shell qui est modifié par
|
||||
<code>cd</code>, ce qui signifie que le script suivant :
|
||||
Certaines commandes du shell ne sont pas des programmes mais des
|
||||
commandes <em>internes</em> (<em>builtins functions</em>). Comme nous
|
||||
l'avons vu, elles sont directement reconnues et exécutées par le shell.
|
||||
Un exemple de commande interne est <code>cd</code> ; elle modifie
|
||||
le répertoire courant du shell.
|
||||
</p>
|
||||
|
||||
<div class="attention">
|
||||
<p>
|
||||
Attention : si vous créez un script (c'est-à-dire un programme
|
||||
écrit en langage shell) qui utilise <code>cd</code>, il ne modifie pas
|
||||
le répertoire courant du shell qui lance ce script, mais celui d'un
|
||||
shell qui est créé à l'occasion de l'exécution de ce script, et qui
|
||||
meurt à la fin de cette exécution.</p>
|
||||
|
||||
<p> Exemple : je crée un script <code>aller</code> qui contient les
|
||||
lignes suivantes : </p>
|
||||
|
||||
<pre>
|
||||
#! /bin/sh
|
||||
cd $*</pre>
|
||||
|
||||
<p class="continue">
|
||||
ne marche pas, car le shell lance un autre shell pour exécuter le script.
|
||||
C'est ce sous-shell qui change son répertoire courant, et ce changement est
|
||||
perdu quand le sous-shell meurt.
|
||||
<p>
|
||||
Nous aurons alors :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<span class="prompt">chaland ~ $</span> aller toto
|
||||
<span class="prompt">chaland ~ $</span> cd toto
|
||||
<span class="prompt">chaland ~/toto $</span></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<h3><a name="prog">Quels programmes utilisent le langage du shell ?</a></h3>
|
||||
|
||||
<p>
|
||||
Scripts pour automatiser ou systématiser des tâches,
|
||||
opérations un peu compliquées.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
sh : .profile (shell de login) ; sh lance un autre shell qui prend la relève
|
||||
pour la session.
|
||||
.xinitrc (pour lancer X)
|
||||
La répétition de commandes complexes en ligne de commande du shell est
|
||||
rapidement fastidieuse ; aussi est-il très pratique de connaître
|
||||
les bases de la programmation de scripts shell. Les scripts servent à
|
||||
automatiser ou systématiser des tâches.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -90,9 +187,22 @@ config conscrits. Il est n
|
|||
options.
|
||||
</p>
|
||||
|
||||
<p> Il existe encore le script <code>.xinitrc</code>, qui lance X ;
|
||||
X est le gestionnaire de fenêtres classique sous Unix.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Le nombre de scripts possibles est illimité ; vous pouvez en créer
|
||||
autant que vous voulez, selon vos besoins : c'est ainsi que l'on
|
||||
personnalise son système et qu'on l'adapte à ses exigences, plutôt que
|
||||
l'inverse.
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a name="ligne">La ligne de commande</a></h2>
|
||||
|
||||
<h3><a name="raccourcis">Raccourcis pour les noms de fichiers</a></h3>
|
||||
<h3><a name="raccourcis">Raccourcis pour les noms de fichiers : les
|
||||
jokers</a></h3>
|
||||
|
||||
<p>
|
||||
Il est parfois ennuyeux d'avoir à taper un nom complet de fichier comme
|
||||
|
@ -107,13 +217,13 @@ Pour
|
|||
(<em>wildcards</em> en anglais).
|
||||
</p>
|
||||
|
||||
<h4>L'étoile</h4>
|
||||
<h4>L'étoile : *</h4>
|
||||
|
||||
<p>
|
||||
Une <strong>étoile</strong> <code>*</code> dans un nom de fichier est
|
||||
interprétée par le shell comme « n'importe quelle séquence de
|
||||
caractères » (mais ça ignore les fichiers dont le nom commence par un
|
||||
point). Exemple:
|
||||
point). Exemple :
|
||||
</p>
|
||||
|
||||
<pre>cc -o foo *.c</pre>
|
||||
|
@ -128,7 +238,7 @@ ex
|
|||
|
||||
<pre>cc -o foo bar.c buz.c foo.c gee.c gog.c</pre>
|
||||
|
||||
<h4>Le point d'interrogation</h4>
|
||||
<h4>Le point d'interrogation : ?</h4>
|
||||
|
||||
<p>
|
||||
On a aussi le <strong>point d'interrogation</strong> <code>?</code>, qui
|
||||
|
@ -137,7 +247,7 @@ de nom). Par exemple, <code>ls *.?</code> liste tous les dont l'extension
|
|||
ne comporte qu'un caractère (<code>.c</code>, <code>.h</code>...).
|
||||
</p>
|
||||
|
||||
<h4>Les crochets</h4>
|
||||
<h4>Les crochets : []</h4>
|
||||
|
||||
<p>
|
||||
La forme <code>[abcd]</code> remplace un caractère quelconque parmi
|
||||
|
@ -208,7 +318,7 @@ backslash est lui-m
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Exemples:
|
||||
Exemples :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -221,20 +331,21 @@ Exemples:
|
|||
|
||||
<p>
|
||||
Un autre moyen est d'inclure une chaîne de caractères entre apostrophes
|
||||
(simples quotes) <code>'</code>. Tout ce qui se trouve entre deux apostrophes
|
||||
sera passé tel quel par le shell à la commande.
|
||||
Exemple:
|
||||
(simples quotes) <code>'</code>. Tout ce qui se trouve entre deux
|
||||
apostrophes sera passé tel quel par le shell à la
|
||||
commande. Exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<span class="prompt">chaland ~ $</span> echo '$?*'
|
||||
$?*</pre>
|
||||
|
||||
<h4>Les guillemets doubles ou doubles quotes (<code>"</code>)</h4>
|
||||
<h4>Les guillemets doubles ou doubles quotes (<code>"</code>)</h4>
|
||||
|
||||
<p>
|
||||
Les guillemets se comportent comme les apostrophes, à une exception près: les
|
||||
dollars et les backslashes sont interprétés entre les guillemets. Exemple:
|
||||
dollars et les backslashes sont interprétés entre les guillemets.
|
||||
Exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -242,8 +353,9 @@ dollars et les backslashes sont interpr
|
|||
/users/87/maths/doligez/*</pre>
|
||||
|
||||
<p>
|
||||
Une technique utile: Quand on juxtapose deux chaînes de caractères quotées, le
|
||||
shell les concatène, et elles ne forment qu'un argument. Exemple:
|
||||
Une technique utile: Quand on juxtapose deux chaînes de caractères
|
||||
quotées, le shell les concatène, et elles ne forment qu'un argument.
|
||||
Exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -263,7 +375,7 @@ de savoir si
|
|||
Dernière forme de quotation: <code>`<em>commande</em>`</code>. Le shell
|
||||
exécute la <em>commande</em> indiquée entre backquotes, lit la sortie de la
|
||||
commande mot par mot, et remplace <code>`</code> <em>commande</em>
|
||||
<code>`</code> par la liste de ces mots. Exemple :
|
||||
<code>`</code> par la liste de ces mots. Exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -284,20 +396,92 @@ commande it <em>cmd</em>
|
|||
/usr/local/bin/emacs</pre>
|
||||
|
||||
|
||||
<h3><a name="redirections">Redirections</a></h3>
|
||||
<h3><a name="redirections">Entrée, sortie et redirection</a></h3>
|
||||
|
||||
<h4>Entrée et sortie</h4>
|
||||
|
||||
<p>
|
||||
Chaque commande a une <em>entrée standard</em>, une <em>sortie standard</em>,
|
||||
et une <em>sortie d'erreur</em>. Par défaut, l'entrée standard est le clavier,
|
||||
la sortie standard est l'écran, et la sortie d'erreur est aussi l'écran.
|
||||
Un programme consiste à traiter des données, et à renvoyer des données
|
||||
transformées : il transforme des informations, et c'est pourquoi
|
||||
l'on parle d'<em>informatique</em>.</p>
|
||||
|
||||
<p> Prenons le programme <code>hachoir</code>, par exemple : on y
|
||||
fait entrer des choses, elles sortent sous une autre forme, et dans
|
||||
l'intervalle, elles subissent des transformations régulières. Par
|
||||
exemple, on fait entrer une vache, il en ressort du steak haché ;
|
||||
on y fait entrer des carottes, il en ressort des carottes rapées.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Deux concepts permettent de modéliser cette transformation
|
||||
d'informations : les concepts d'entrée et de
|
||||
sortie. L'<strong>entrée</strong>, c'est la vache ou les carottes ;
|
||||
la <strong>sortie</strong>, c'est le steak haché ou les carottes
|
||||
rapées.
|
||||
</p>
|
||||
|
||||
<h4>Sortie standard et sortie d'erreur</h4>
|
||||
|
||||
<p>
|
||||
Mais cette première distinction entre entrée et sortie ne suffit pas,
|
||||
car la sortie d'un programme, c'est-à-dire les messages qu'il renvoie,
|
||||
sont de deux ordres : il y a les <em>messages normaux</em> relevant
|
||||
de la transformation d'informations (par exemple le steak haché ou les
|
||||
carottes rapées), mais il y a aussi des <em>messages d'erreur</em>.</p>
|
||||
|
||||
<p> Par exemple, si vous mettez, sur le tapis roulant qui mène au
|
||||
hachoir, un objet trop gros pour y rentrer, le hachoir, s'il est bien
|
||||
conçu, devra vous prévenir qu'il n'arrive pas à hacher un objet si
|
||||
gros. Et ce message, quoiqu'il sorte aussi bien du hachoir que le steak
|
||||
haché, ne doit pas être traité de la même façon à sa sortie, et n'est
|
||||
pas suivi des mêmes conséquences. C'est pourquoi l'on distingue la
|
||||
<strong>sortie standard</strong> et la <strong>sortie d'erreur</strong>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pour résumer, chaque commande a donc :</p>
|
||||
<ul>
|
||||
<li> une <em>entrée standard</em>, </li>
|
||||
<li> une <em>sortie standard</em> et </li>
|
||||
<li> une <em>sortie d'erreur</em>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h4>Comportement par défaut</h4>
|
||||
|
||||
<p> Par défaut, l'entrée standard est le clavier, la sortie standard est
|
||||
l'écran, et la sortie d'erreur est aussi l'écran.</p>
|
||||
|
||||
<p> C'est sur le clavier que vous tapez ; ce que vous tapez et ce
|
||||
que renvoient les programmes s'inscrit à l'écran ; les messages
|
||||
d'erreur renvoyés par les programmes s'affichent à l'écran.
|
||||
</p>
|
||||
|
||||
<h4>Les redirections</h4>
|
||||
|
||||
<p>
|
||||
Mais il ne s'agit là que du comportement par défaut, et pas d'un
|
||||
comportement obligatoire. Vous pouvez tout à fait orienter différemment
|
||||
vos programmes.</p>
|
||||
|
||||
<p> Par exemple, si vous donnez une vache comme entrée au hachoir, vous
|
||||
pouvez orienter la sortie vers une imprimante (au lieu de l'écran,
|
||||
proposé par défaut), et vous imprimerez ainsi du steak haché. </p>
|
||||
|
||||
<p>
|
||||
Ou encore, vous pouvez donner un plant de carottes comme entrée au
|
||||
programme <code>cueillette</code>, et envoyer la sortie (c'est-à-dire
|
||||
les carottes cueillies) au programme <code>hachoir</code>.
|
||||
</p>
|
||||
|
||||
|
||||
<h4>Rediriger la sortie dans un fichier : <code>></code></h4>
|
||||
|
||||
<p>
|
||||
On peut <em> rediriger</em> la sortie standard d'une commande vers un fichier
|
||||
(caractère <code>></code>). Le résultat de la commande sera placé dans le
|
||||
fichier au lieu de s'afficher sur l'écran. Exemple:
|
||||
On peut <em> rediriger</em> la sortie standard d'une commande vers un
|
||||
fichier (caractère « <code>></code> »). Le résultat de la
|
||||
commande sera placé dans le fichier au lieu de s'afficher sur l'écran.
|
||||
Exemple :
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span> ls -l > foo</pre>
|
||||
|
@ -314,12 +498,41 @@ dans le fichier <code>foo</code>. On peut alors taper
|
|||
pour lire le fichier page par page.
|
||||
</p>
|
||||
|
||||
|
||||
<h4>Ajouter la sortie à un fichier : <code>>></code></h4>
|
||||
|
||||
<p> On veut parfois ajouter la sortie d'un programme à un fichier, sans
|
||||
effacer ce qui précède. Or, par défaut, si l'on tape plusieurs fois
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span> ls -l > foo</pre>
|
||||
|
||||
<p class="continue">
|
||||
à chaque fois, le contenu antérieur du fichier <code>foo</code> est
|
||||
écrasé par le contenu ultérieur.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pour éviter cela, il existe l'outil de redirection >>. Ainsi, si
|
||||
vous tapez plusieurs fois
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span> ls -l >> foo</pre>
|
||||
|
||||
<p class="continue">
|
||||
le fichier <code>foo</code> contiendra <em>à la suite</em> tout ce que
|
||||
vous a renvoyé la commande.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h4>Rediriger l'entrée : <code><</code></h4>
|
||||
|
||||
<p>
|
||||
On peut aussi rediriger l'entrée standard d'une commande (caractère
|
||||
<code><</code>). La commande lira alors le fichier au lieu du clavier.
|
||||
Exemple:
|
||||
« <code><</code> »). La commande lira alors le fichier au
|
||||
lieu du clavier. Exemple :
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span> elm leroy < foo</pre>
|
||||
|
@ -339,19 +552,64 @@ standard et l'affiche page par page sur le terminal.
|
|||
<code>|</code></h4>
|
||||
|
||||
<p>
|
||||
On peut se passer du fichier intermédiaire grâce à un <em>pipe</em>
|
||||
(caractère <code>|</code>). Un pipe connecte directement la sortie standard d'une
|
||||
commande sur l'entrée standard d'une autre commande. Exemple: pour afficher
|
||||
page par page la liste des fichiers du répertoire courant, faire
|
||||
Il devient rapidement ennuyeux de taper :
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span> ls -l > foo
|
||||
<span class="prompt">chaland ~ $</span> less < foo
|
||||
<span class="prompt">chaland ~ $</span> rm foo</pre>
|
||||
|
||||
<p>
|
||||
On peut se passer du fichier intermédiaire (<code>foo</code> dans notre
|
||||
exemple) grâce à un <em>pipe</em> (caractère
|
||||
« <code>|</code> »). Un pipe connecte directement la sortie
|
||||
standard d'une commande sur l'entrée standard d'une autre commande.
|
||||
Exemple : pour afficher page par page la liste des fichiers du
|
||||
répertoire courant, faire
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~ $</span> ls -l | less</pre>
|
||||
|
||||
<p>
|
||||
Le pipe est d'un usage très courant et rend beaucoup de services.
|
||||
Le pipe, ou tube, est d'un usage très courant, et rend beaucoup de
|
||||
services.
|
||||
</p>
|
||||
|
||||
<h4>Récapitulatif</h4>
|
||||
|
||||
|
||||
<h3>Succès et erreur</h3>
|
||||
|
||||
<p>
|
||||
On a parfois besoin de savoir si une commande a réussi ou non avant d'en
|
||||
lancer une autre. Les indicateurs <code>&&</code> et
|
||||
<code>||</code> permettent, respectivement, de lancer une commande si
|
||||
(et seulement si) la précédente a réussi ou échoué.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Par exemple, si j'ai un fichier <code>foo</code>, j'obtiens :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<span class="prompt">chaland ~ $</span> ls foo && echo "J'ai un fichier foo."
|
||||
foo
|
||||
J'ai un fichier foo.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Si je n'ai pas de fichier <code>foo</code>, le message ne s'affiche
|
||||
pas. En revanche, si je tape alors :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<span class="prompt">chaland ~ $</span> ls foo || echo "Je n'ai pas de fichier foo."
|
||||
ls: foo: No such file or directory
|
||||
Je n'ai pas de fichier foo.
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<h3>Récapitulatif</h3>
|
||||
|
||||
<p>
|
||||
La panoplie complète des redirections est la suivante (le tableau indique les
|
||||
|
@ -379,11 +637,19 @@ premi
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Redirection des sorties standard et d'erreur</h3>
|
||||
|
||||
<p>
|
||||
Il est parfois utile de rediriger la sortie standard et la sortie
|
||||
d'erreur vers un même endroit. Pour cela, on utilise le motif
|
||||
<code>2>&1</code> avant la redirection.
|
||||
</p>
|
||||
|
||||
<table class="tableau">
|
||||
<tr>
|
||||
<th> Fonction </th>
|
||||
<th> Bourne shell </th>
|
||||
<th> Z-shell </th>
|
||||
<th> Bourne shell (sh, bash) </th>
|
||||
<th> Z-shell (zsh) </th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Redirige la sortie d'erreur (2) et la sortie standard (1) sur l'entrée
|
||||
|
@ -472,12 +738,79 @@ Affiche les 10 derniers mots du dictionnaire qui contiennent la cha
|
|||
|
||||
<h3><a name="variables">Variables</a></h3>
|
||||
|
||||
<h4>Qu'est-ce qu'une variable ?</h4>
|
||||
|
||||
<p>
|
||||
Le shell a des variables. Pour désigner le contenu d'une variable, on écrit
|
||||
le nom de la variable précédé d'un dollar. Exemple: <code>echo $HOME</code>
|
||||
affiche le nom du répertoire personnel de l'utilisateur.
|
||||
Une variable est l'assignation d'une étiquette à un contenu ; ce
|
||||
contenu, comme l'indique le mot « variable », peut changer
|
||||
autant que l'on veut ; l'assignation de l'étiquette à ce contenu,
|
||||
elle, est fixe, aussi longtemps que l'on ne dissout pas la
|
||||
variable. </p>
|
||||
|
||||
<p>
|
||||
La notion de variable est commune à presque tous les langages
|
||||
informatiques, et en particulier aux langages de programmation. Ceux qui
|
||||
ont déjà manipulé des langages sont donc familiers avec cette
|
||||
notion. Pour les autres, un petit exemple les aidera peut-être à la
|
||||
saisir.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Mettons que vous programmiez le hachoir dont nous parlions plus haut. Un
|
||||
hachoir est un instrument dangereux, à ne pas mettre à la portée des
|
||||
enfants. Robert le jardinier, qui a conçu ce hachoir, veut être le seul
|
||||
à pouvoir l'utiliser, sans quoi le petit Émile pourrait se blesser en y
|
||||
mettant le doigt.</p>
|
||||
|
||||
<p> Ainsi, il va dire au programme <code>hachoir</code> de vérifier la
|
||||
variable <code>USER</code>, qui contient le nom de l'utilisateur. Si le
|
||||
nom « Robert » est associé à l'étiquette <code>USER</code>,
|
||||
alors le programme se met en route ; sinon, il dit à l'utilisateur
|
||||
de ne pas utiliser cet instrument sans la présence d'un adulte, et de
|
||||
bien regarder des deux côtés avant de traverser la rue.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Certaines variables sont prédéfinies, par exemple
|
||||
<code>USER</code> ; mais on peut en créer autant que l'on veut. Par
|
||||
exemple, si Robert veut autoriser d'autres adultes que lui à utiliser
|
||||
son hachoir, il peut faire que le programme demande à l'utilisateur quel
|
||||
âge il a ; la réponse est enregistrée dans la variable
|
||||
<code>age</code> ; ensuite, le programme va examiner le contenu de
|
||||
cette variable. Si <code>age >= 18</code>, alors le hachoir peut se
|
||||
mettre en route ; mais si <code>age < 18</code>, le hachoir
|
||||
refuse de se mettre en marche.
|
||||
</p>
|
||||
|
||||
<h4>Les variables en shell</h4>
|
||||
|
||||
<p>
|
||||
En shell, pour désigner le contenu d'une variable, on écrit le nom de la
|
||||
variable précédé du signe dollar. Exemple : <code>echo
|
||||
$HOME</code> affiche le nom du répertoire personnel de l'utilisateur,
|
||||
mémorisé par la variable <code>HOME</code>.
|
||||
</p>
|
||||
|
||||
<h5>Les noms de variables</h5>
|
||||
|
||||
<p>
|
||||
Par convention, les variables relevant du système, comme
|
||||
<code>HOME</code>, <code>USER</code> et beaucoup d'autres, sont en
|
||||
majuscules, tandis que l'on recommande d'écrire en minuscules les
|
||||
variables que l'on se crée soi-même. On évite ainsi la désagréable
|
||||
surprise de remplacer une variable importante et de casser tout ou
|
||||
partie de son système.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Les noms de variables sont en effet sensibles à la casse :
|
||||
<code>USER</code>, <code>user</code>, <code>User</code>,
|
||||
<code>uSeR</code> etc. sont des variables différentes.
|
||||
</p>
|
||||
|
||||
|
||||
<h5>Définir une variable</h5>
|
||||
|
||||
<p>
|
||||
La façon de donner une valeur à une variable varie selon le type de shell
|
||||
utilisé :
|
||||
|
@ -504,11 +837,14 @@ Famille des <strong>Bourne Shell</strong> (<code>sh</code>, <code>bash</code>,
|
|||
<span class="prompt">chaland ~ $</span> echo $foo
|
||||
bar</pre>
|
||||
|
||||
|
||||
<h5>Les variables d'environnement</h5>
|
||||
|
||||
<p>
|
||||
Les valeurs des variables sont accessibles aux commandes lancées par le shell.
|
||||
L'ensemble de ces valeurs constitue l'<em>environnement</em>. On peut aussi
|
||||
supprimer une variable de l'environnement avec <code>unsetenv</code>
|
||||
(C-Shell) ou <code>unset</code> (Bourne Shell).
|
||||
Les valeurs des variables sont accessibles aux commandes lancées par le
|
||||
shell. L'ensemble de ces valeurs constitue l'<em>environnement</em>.
|
||||
On peut aussi supprimer une variable de l'environnement avec
|
||||
<code>unsetenv</code> (C-Shell) ou <code>unset</code> (Bourne Shell).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -516,29 +852,23 @@ Quelques variables d'environnement:
|
|||
</p>
|
||||
|
||||
<ul>
|
||||
<li><code>DISPLAY</code> : L'écran sur lequel les programmes X travaillent.
|
||||
C'est souvent de la forme : <code>machine.somehost.somewhere:0.0</code>
|
||||
Si c'est vide, c'est qu'il n'y a pas d'affichage graphique possible.
|
||||
</li>
|
||||
<li><code>PRINTER</code> : pour les commandes d'impression. Contient le nom de
|
||||
l'imprimante sur laquelle il faut envoyer vos fichiers.
|
||||
</li>
|
||||
<li><code>EDITOR</code> : utilisée par <code>mutt</code>, <code>forum</code>,
|
||||
et beaucoup d'autres commandes. Contient le nom de votre éditeur de textes
|
||||
préféré.
|
||||
</li>
|
||||
<li><code>VISUAL</code> : la même chose qu'<code>EDITOR</code>.
|
||||
</li>
|
||||
<li><code>SHELL</code> : contient le nom de votre shell.
|
||||
</li>
|
||||
<li><code>DISPLAY</code> : L'écran sur lequel les programmes X
|
||||
travaillent. Cette variable est souvent de la forme :
|
||||
<code>machine.somehost.somewhere:0.0</code> Si cette variable est vide,
|
||||
c'est qu'il n'y a pas d'affichage graphique possible. </li>
|
||||
<li><code>PRINTER</code> : pour les commandes d'impression. Contient le
|
||||
nom de l'imprimante sur laquelle il faut envoyer vos fichiers. </li>
|
||||
<li><code>EDITOR</code> : utilisée par <code>mutt</code>,
|
||||
<code>forum</code>, et beaucoup d'autres commandes. Contient le nom de
|
||||
votre éditeur de textes préféré. </li>
|
||||
<li><code>VISUAL</code> : la même chose qu'<code>EDITOR</code>. </li>
|
||||
<li><code>SHELL</code> : contient le nom de votre shell. </li>
|
||||
<li><code>HOME</code> : contient le nom de votre répertoire personnel.
|
||||
</li>
|
||||
<li><code>USER</code> : contient votre nom de login.
|
||||
</li>
|
||||
<li><code>LOGNAME</code> : la même chose que <code>USER</code>.
|
||||
</li>
|
||||
<li><code>PATH</code> : contient une liste de répertoires dans lesquels le
|
||||
shell va chercher les commandes.
|
||||
<li><code>USER</code> : contient votre nom de login. </li>
|
||||
<li><code>LOGNAME</code> : la même chose que <code>USER</code>. </li>
|
||||
<li><code>PATH</code> : contient une liste de répertoires dans lesquels
|
||||
le shell va chercher les commandes.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -559,75 +889,173 @@ nous avons d
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Pour la programmation du shell, nous allons utiliser le shell <code>sh</code>,
|
||||
qui est le plus répandu et standard. Ce que nous avons vu jusqu'ici
|
||||
s'applique aussi bien à <code>sh</code> qu'à <code>zsh</code> et aussi à
|
||||
<code>csh</code>, à l'exception de <code>setenv</code> et de certaines
|
||||
redirections signalées. Pour être un script, un fichier doit commencer par
|
||||
la ligne:
|
||||
</p>
|
||||
Pour la programmation du shell, nous allons utiliser le shell
|
||||
<code>sh</code>, qui est le plus répandu et standard. Ce que nous avons
|
||||
vu jusqu'ici s'applique aussi bien à <code>sh</code> qu'à
|
||||
<code>zsh</code> et aussi à <code>csh</code>, à l'exception de
|
||||
<code>setenv</code> et de certaines redirections signalées. </p>
|
||||
|
||||
|
||||
<h3>Rendre un script exécutable</h3>
|
||||
|
||||
<p> Pour être un script, un fichier doit commencer par la ligne: </p>
|
||||
|
||||
<pre>#!/bin/sh</pre>
|
||||
|
||||
<p>
|
||||
Il doit aussi avoir être exécutable (bit <code>x</code>). Le
|
||||
<code>#!/bin/sh</code> sur la première ligne indique que ce script doit être
|
||||
exécuté par le shell <code>sh</code> dont on indique le chemin d'accès.
|
||||
exécuté par le shell <code>sh</code> dont on indique le chemin
|
||||
d'accès. Pour rendre un fichier exécutable, tapez :
|
||||
</p>
|
||||
|
||||
<pre><span class="prompt">chaland ~</span> chmod u+x fichier
|
||||
</pre>
|
||||
|
||||
<p class="continue">
|
||||
(pour en savoir plus sur les droits attachés à un fichier, consultez la
|
||||
page sur <a href="droits.html">les droits d'accès</a>).
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h3><a name="structures">Structures de contrôle</a></h3>
|
||||
|
||||
|
||||
<h4>for</h4>
|
||||
|
||||
<pre>for <em>var</em> in <em>liste de chaînes</em> ;
|
||||
do <em>commandes</em> ; done</pre>
|
||||
<p>
|
||||
C'est avec les structures de contrôle qu'un programme peut commencer à
|
||||
devenir sérieux. Le principe général de ces structures est le
|
||||
suivant : adapter le comportement du programme selon les réponses
|
||||
apportées à certaines questions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Affecte successivement à la variable de nom <em>var</em> chaque chaîne de
|
||||
caractères trouvée dans la <em>liste de chaînes</em>, et exécute les
|
||||
<em>commandes</em> une fois pour chaque chaîne.
|
||||
Nous avons déjà vu une application possible des structures de contrôle
|
||||
en parlant des variables. Le programme <code>hachoir</code> conçu par
|
||||
Robert le jardinier pose la question suivante : est-ce que
|
||||
<code>$USER</code> vaut « Robert » ?
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> si oui, alors le hachoir doit se mettre en marche ;</li>
|
||||
<li> si non, alors le hachoir doit refuser de se mettre en
|
||||
marche.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h4>La boucle <code>if</code></h4>
|
||||
|
||||
<p>
|
||||
La structure de contrôle <code>if</code> est la plus courante de toutes,
|
||||
et la plus élémentaire. Elle est constituée de quatre termes :</p>
|
||||
|
||||
<ol>
|
||||
<li> <code>if</code> (si), qui marque la condition à remplir ;
|
||||
</li>
|
||||
<li> <code>then</code> (alors), qui marque les conséquences si la
|
||||
condition est remplie ; </li>
|
||||
<li> <code>else</code> (sinon), qui est facultatif et marque le
|
||||
comportement à adopter si la condition n'est pas remplie ; </li>
|
||||
<li> <code>fi</code> (<code>if</code> à l'envers), qui marque la fin de
|
||||
la boucle.</li>
|
||||
</ol>
|
||||
|
||||
<pre>if <em>commande</em> ; then <em>commandes</em> ; else <em>commandes</em> ; fi</pre>
|
||||
|
||||
<p class="continue"> ou bien (car le point et virgule équivaut à un saut
|
||||
de ligne) :</p>
|
||||
|
||||
<pre>if <em>commande</em>
|
||||
then <em>commandes</em>
|
||||
else <em>commandes</em>
|
||||
fi</pre>
|
||||
|
||||
<p>
|
||||
Par exemple, pour Robert le jardinier, on aura :
|
||||
</p>
|
||||
|
||||
<pre>if [[ $USER == "Robert"]]
|
||||
then hacher_menu
|
||||
else echo "Quand tu seras grand, $USER."
|
||||
echo "Et fais bien attention en traversant la rue."
|
||||
fi</pre>
|
||||
|
||||
|
||||
|
||||
<h4>La boucle <code>for</code></h4>
|
||||
|
||||
<p>
|
||||
La boucle <code>for</code> affecte successivement une variable chaque
|
||||
chaîne de caractères trouvée dans une <em>liste de chaînes</em>, et
|
||||
exécute les <em>commandes</em> une fois pour chaque chaîne.
|
||||
</p>
|
||||
|
||||
<pre>for <em>var</em> in <em>liste de chaînes</em> ; do <em>commandes</em> ; done</pre>
|
||||
|
||||
<p class="continue"> ou bien :</p>
|
||||
|
||||
<pre>for <em>var</em> in <em>liste de chaînes</em>
|
||||
do <em>commandes</em>
|
||||
done</pre>
|
||||
|
||||
|
||||
<p>
|
||||
Rappel : <code>$<em>var</em></code> accède à la valeur courante de
|
||||
<em>var</em>. La partie <em>commandes</em> est une suite de commandes,
|
||||
séparées par des <code>;</code> ou des retours à la ligne. (Tous les
|
||||
<code>;</code> dans cette syntaxe peuvent aussi être remplacés par des
|
||||
retours à la ligne.)
|
||||
séparées par des points et virgules (<code>;</code>) ou des retours à la
|
||||
ligne.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Exemple :
|
||||
Exemple :
|
||||
</p>
|
||||
|
||||
<pre>for i in *; do echo $i; done</pre>
|
||||
<pre>for i in *; do echo "$i"; done</pre>
|
||||
|
||||
<p class="continue">
|
||||
affiche les noms de tous les fichiers du répertoire courant, un par ligne.
|
||||
</p>
|
||||
|
||||
<h4>if</h4>
|
||||
|
||||
<pre>if <em>commande</em> ; then <em>commandes</em> ;
|
||||
else <em>commandes</em> ; fi</pre>
|
||||
|
||||
<p>
|
||||
Exécute l'une ou l'autre des listes de <em>commandes</em>, suivant que la
|
||||
première <em>commande</em> a réussi ou non (voir ci-dessous).
|
||||
Remarque : plus un programme grossit, plus il importe que son
|
||||
contenu soit lisible. <strong>Les noms de variable doivent donc être le
|
||||
plus lisibles possible</strong>, pour permettre à d'autres gens, ou bien
|
||||
à vous-même dans quelques mois, de comprendre rapidement votre script.
|
||||
Ainsi, il peut être plus explicite d'écrire, au lieu de « <code>for
|
||||
i in *; do echo "$i"; done</code> » :
|
||||
</p>
|
||||
|
||||
<h4>while</h4>
|
||||
|
||||
<pre>while <em>commande</em> ; do <em>commande</em> ; done</pre>
|
||||
<pre>for fichier in *; do echo "$fichier"; done</pre>
|
||||
|
||||
<p>
|
||||
Exécute les <em>commandes</em> de manière répétée tant que la première
|
||||
<em>commande</em> réussit.
|
||||
En outre, pour des raisons de lisibilité, <strong>n'hésitez pas à
|
||||
gaspiller des lignes de code</strong> en sautant des lignes ; les
|
||||
lignes de code ne sont pas une ressource rare :
|
||||
</p>
|
||||
|
||||
<h4>case</h4>
|
||||
<pre>for fichier in *
|
||||
do echo "$fichier"
|
||||
done</pre>
|
||||
|
||||
|
||||
|
||||
<h4>La boucle <code>while</code></h4>
|
||||
|
||||
<pre>while <em>commande</em>
|
||||
do <em>commande</em>
|
||||
done</pre>
|
||||
|
||||
<p>
|
||||
La boucle <code>while</code> exécute les <em>commandes</em> de manière
|
||||
répétée tant que la première <em>commande</em> réussit.</p>
|
||||
|
||||
<p> Par exemple : <em>tant que</em> le mot de passe correct n'a pas
|
||||
été donné, refuser l'accès et redemander le mot de passe.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h4>La boucle <code>case</code></h4>
|
||||
|
||||
<pre>case <em>chaîne</em> in
|
||||
<em>pattern</em>) <em>commande</em> ;;
|
||||
|
@ -635,11 +1063,12 @@ Ex
|
|||
esac</pre>
|
||||
|
||||
<p>
|
||||
Exécute la première <em>commande</em> telle que la <em>chaîne</em> est de la
|
||||
forme <em>pattern</em>. Un <em>pattern</em> est un mot contenant
|
||||
éventuellement les constructions <code>*</code>, <code>?</code>,
|
||||
<code>[a-d]</code>, avec la même signification que pour les raccourcis dans
|
||||
les noms de fichiers. Exemple :
|
||||
La boucle <code>case</code> exécute la première <em>commande</em> telle
|
||||
que la <em>chaîne</em> est de la forme <em>pattern</em>. Un
|
||||
<em>pattern</em> (motif) est un mot contenant éventuellement les
|
||||
constructions <code>*</code>, <code>?</code>, <code>[a-d]</code>, avec
|
||||
la même signification que pour les raccourcis dans les noms de
|
||||
fichiers. Exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -649,6 +1078,11 @@ case $var in
|
|||
*) echo 'Autre chose';;
|
||||
esac</pre>
|
||||
|
||||
<p>
|
||||
Vous observerez que l'on clôt la boucle <code>case</code> avec
|
||||
<code>esac</code>, qui est le mot <code>case</code> à l'envers, de même
|
||||
que l'on clôt <code>if</code> avec <code>fi</code>.
|
||||
</p>
|
||||
|
||||
<h3><a name="retour">Code de retour</a></h3>
|
||||
|
||||
|
@ -656,20 +1090,23 @@ esac</pre>
|
|||
On remarque que la condition des commandes <code>if</code> et
|
||||
<code>while</code> est une commande. Chaque commande renvoie un code de
|
||||
retour (qui est ignoré en utilisation normale). Si le code est 0, la
|
||||
commande a réussi; sinon, la commande a échoué. Par exemple, le compilateur
|
||||
<code>cc</code> renvoie un code d'erreur non nul si le fichier compilé
|
||||
contient des erreurs, ou s'il n'existe pas.
|
||||
commande a réussi ; sinon, la commande a échoué. Par exemple, le
|
||||
compilateur <code>cc</code> renvoie un code d'erreur non nul si le
|
||||
fichier compilé contient des erreurs, ou s'il n'existe pas.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Les commandes <code>if</code> et <code>while</code> considèrent donc le code
|
||||
de retour 0 comme « vrai », et tout autre code comme « faux ».
|
||||
Les commandes <code>if</code> et <code>while</code> considèrent donc le
|
||||
code de retour 0 comme « vrai », et tout autre code comme
|
||||
« faux ».
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Il existe une commande <code>test</code>, qui évalue des expressions booléennes
|
||||
passées en argument, et renvoie un code de retour en fonction du résultat.
|
||||
Elle est bien utile pour les scripts. Exemple :
|
||||
Il existe une commande <code>test</code>, qui évalue des expressions
|
||||
booléennes (c'est-à-dire dont la valeur ne peut être que vraie ou
|
||||
fausse, 1 ou 0) passées en argument, et renvoie un code de retour en
|
||||
fonction du résultat. Elle est bien utile pour les scripts.
|
||||
Exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
@ -733,8 +1170,8 @@ entra
|
|||
|
||||
<div class="metainformation">
|
||||
Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez.
|
||||
Ajustements : Nicolas George.
|
||||
Dernière modification le 2002-12-16.
|
||||
Ajustements : Nicolas George. Compléments : Baptiste Mélès.
|
||||
Dernière modification le <date value="$Date: 2005-05-28 11:05:39 $" />.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
Loading…
Add table
Reference in a new issue