tuteurs.ens.fr/unix/shell/entreesortie.tml

401 lines
12 KiB
Text
Raw Normal View History

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
"tuteurs://DTD/tml.dtd">
<html>
<head>
<title>Entrée/sortie</title>
</head>
<body>
<h1>Entrée, sortie, redirection</h1>
<h2><a name="redirections">Entrée et sortie</a></h2>
<h3>Que sont l'entrée et la sortie d'une commande ?</h3>
<p>
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 un 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>
<h3>Sortie standard et sortie d'erreur</h3>
<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>
<h3>Comportement par défaut</h3>
<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>
<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>
<h2>Les redirections</h2>
<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>
<p>
Nous allons étudier successivement :
</p>
<ul>
<li> comment rediriger la sortie d'une commande vers un
fichier ;</li>
<li> comment ajouter la sortie d'une commande à la fin d'un
fichier ;</li>
<li> comment utiliser un fichier comme entrée d'une commande ;</li>
<li> comment utiliser la sortie d'une commande comme entrée d'une
autre.</li>
</ul>
<p>
Ces différentes configurations esquissent la grammaire d'une utilisation
très performante des fonctionnalités du shell ; <strong>vous saurez
en effet comment brancher un fichier sur l'entrée ou sur la sortie d'une
commande, et comment brancher la sortie d'une commande sur l'entrée
d'une autre</strong>. Il n'y a pas d'autre combinaison possible.
</p>
<h3>Rediriger la sortie dans un fichier : <code>&gt;</code></h3>
<p>
On peut <em> rediriger</em> la sortie standard d'une commande vers un
fichier (caractère « <code>&gt;</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 &gt; foo</pre>
<p>
Le résultat de <code>ls -l</code> ne s'affiche pas à l'écran, mais il est placé
dans le fichier <code>foo</code>. On peut alors taper
</p>
<pre><span class="prompt">chaland ~ $</span> less foo</pre>
<p class="continue">
(ou <code>more foo</code>)
pour lire le fichier page par page.
</p>
<h3>Ajouter la sortie à un fichier : <code>&gt;&gt;</code></h3>
<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 &gt; 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 &gt;&gt;. Ainsi, si
vous tapez plusieurs fois
</p>
<pre><span class="prompt">chaland ~ $</span> ls -l &gt;&gt; foo</pre>
<p class="continue">
le fichier <code>foo</code> contiendra <em>à la suite</em> tout ce que
vous a renvoyé la commande.
</p>
<h3>Rediriger l'entrée : <code>&lt;</code></h3>
<p>
On peut aussi rediriger l'entrée standard d'une commande (caractère
« <code>&lt;</code> »). La commande lira alors le fichier au
lieu du clavier. Exemple :
</p>
<pre><span class="prompt">chaland ~ $</span> elm leroy &lt; foo</pre>
<p class="continue">
envoie par mail à Xavier Leroy le résultat de la commande <code>ls -l</code> de
tout à l'heure.
</p>
<p>
On peut aussi taper <code>more &lt; foo</code> qui est équivalent à
<code>more foo</code> car <code>more</code> sans argument lit son entrée
standard et l'affiche page par page sur le terminal.
</p>
<h3>Connecter la sortie d'une commande sur l'entrée d'une autre :
<code>|</code></h3>
<p>
Il devient rapidement ennuyeux de taper :
</p>
<pre><span class="prompt">chaland ~ $</span> ls -l &gt; foo
<span class="prompt">chaland ~ $</span> less &lt; 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, ou tube, est d'un usage très courant, et rend beaucoup de
services.
</p>
<h2>Succès et erreur</h2>
<p>
On a parfois besoin de savoir si une commande a réussi ou non avant d'en
lancer une autre. Les indicateurs <code>&amp;&amp;</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 &amp;&amp; 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>
2005-09-08 01:00:03 +02:00
<p>
Pour en savoir plus sur les structures de test, consultez la page sur
les <a href="test.html">tests et calculs arithmétiques</a>.
2005-09-08 01:00:03 +02:00
</p>
<h2>Redirection des sorties standard et d'erreur</h2>
<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&gt;&amp;1</code> avant la redirection.
</p>
<table class="tableau">
<tr>
<th> Fonction </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
de la commande suivante</td>
<td><code>2&gt;&amp;1 |</code></td>
<td><code> |&amp;</code></td>
</tr>
<tr>
<td>Redirige la sortie d'erreur et la sortie standard dans un fichier</td>
<td><code>2&gt;&amp;1 &gt;</code></td>
<td><code> &gt;&amp;</code></td>
</tr>
<tr>
<td>Redirige la sortie d'erreur et la sortie
standard à la fin d'un fichier existant</td>
<td><code>2&gt;&amp;1 &gt;&gt;</code></td>
<td><code>&gt;&gt;&amp;</code></td>
</tr>
</table>
<h3>Remarques</h3>
<p>
Normalement, une redirection avec <code>&gt;</code> sur un fichier qui
existe déjà efface le contenu du fichier avant d'y placer le résultat de la
commande. Les shells ont des options pour demander confirmation, ou
refuser d'effacer le fichier.
</p>
<p>
Une ligne de commandes contenant des <code>|</code> s'appelle un pipe-line.
Quelques commandes souvent utilisées dans les pipe-lines sont:
</p>
<ul>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/fichiers.html#less">more</a> (ou
<code>less</code>, bien plus évolué) à la fin du pipe-line, affiche le
résultat page par page, pour laisser le temps de le lire. </li>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/divers.html#wc">wc</a> compte le nombre
de caractères, de mots et de lignes de son entrée. </li>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/chercher.html#grep">grep</a> cherche dans
son entrée les lignes contenant un mot donné, et les écrit sur sa sortie.
</li>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/exercices/enchainer.html#syst">sort</a>
lit toutes les lignes de son entrée, les trie, et les écrit dans l'ordre
sur sa sortie. Par défaut l'ordre est alphabétique. </li>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/fichiers.html#head">tail</a> écrit sur sa
sortie les dernières lignes de son entrée. </li>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/fichiers.html#head">head</a> écrit sur sa
sortie les premières lignes de son entrée. </li>
2005-07-05 09:18:06 +02:00
<li><a href="&url.tuteurs;unix/fichiers.html#cat">cat</a> copie
plusieurs fichiers sur sa sortie. </li>
<li><code>fold</code> coupe les lignes de son
entrée à 80 caractères et écrit le résultat sur sa sortie.
</li>
2005-07-05 09:18:06 +02:00
</ul>
<h3>Exemples</h3>
<pre>cat glop buz &gt; toto</pre>
<p>
Concatène les fichiers <code>glop</code> et <code>buz</code> et place le
résultat dans <code>toto</code>.
</p>
<pre>wc -w /usr/dict/words</pre>
<p>
Affiche le nombre de mots du dictionnaire Unix.
</p>
<pre>grep gag /usr/dict/words | tail</pre>
<p>
Affiche les 10 derniers mots du dictionnaire qui contiennent la chaîne
<code>gag</code>.
</p>
<h2>Récapitulatif</h2>
<p>
La panoplie complète des redirections est la suivante :
</p>
<ul>
<li><code>&gt;</code> : change la sortie standard de la commande pour la placer
dans un fichier.
</li>
<li><code>&lt;</code> : change l'entrée standard de la commande pour la prendre
dans un fichier.
</li>
<li><code>|</code> : branche la sortie standard de la commande de gauche sur
l'entrée standard de la commande de droite.
</li>
<li><code>&gt;&gt;</code> : change la sortie standard pour l'ajouter à la fin
d'un fichier existant.
</li>
<li><code>||</code> : exécuter la commande suivante si la première a
échoué.
</li>
<li><code>&amp;&amp;</code> : n'exécuter la commande suivante que si la
première a réussi.
</li>
</ul>
<p>Vous êtes maintenant en mesure de faire ces <a
href="&url.tuteurs;unix/exercices/">exercices</a> pour vous
entraîner. Ou bien vous pouvez revenir à la <a href="index.html">page
centrale sur le shell</a>, d'où vous pourrez vous orienter vers d'autres
2005-09-08 01:00:03 +02:00
parties du cours.</p>
<div class="metainformation">
Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien Doligez.
Modifications : Nicolas George, Baptiste Mélès.
<date value="from git" />
</div>
</body>
</html>