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

393 lines
11 KiB
Text
Raw Normal View History

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
"tuteurs://DTD/tml.dtd">
<html>
<head>
<title>Entr<74>e/sortie</title>
</head>
<body>
<h1>Entr<74>e, sortie, redirection</h1>
<h2><a name="redirections">Entr<74>e et sortie</a></h2>
<h3>Que sont l'entr<74>e et la sortie d'une commande&nbsp;?</h3>
<p>
Un programme consiste <20> traiter des donn<6E>es, et <20> renvoyer des donn<6E>es
transform<EFBFBD>es&nbsp;: 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&nbsp;: on y
fait entrer des choses, elles sortent sous une autre forme, et dans
l'intervalle, elles subissent des transformations r<>guli<6C>res. Par
exemple, on fait entrer une vache, il en ressort du steak hach<63>&nbsp;;
on y fait entrer des carottes, il en ressort des carottes rap<61>es.
</p>
<p>
Deux concepts permettent de mod<6F>liser cette transformation
d'informations&nbsp;: les concepts d'entr<74>e et de
sortie. L'<strong>entr<74>e</strong>, c'est la vache ou les carottes&nbsp;;
la <strong>sortie</strong>, c'est le steak hach<63> ou les carottes
rap<EFBFBD>es.
</p>
<h3>Sortie standard et sortie d'erreur</h3>
<p>
Mais cette premi<6D>re distinction entre entr<74>e et sortie ne suffit pas,
car la sortie d'un programme, c'est-<2D>-dire les messages qu'il renvoie,
sont de deux ordres&nbsp;: il y a les <em>messages normaux</em> relevant
de la transformation d'informations (par exemple le steak hach<63> ou les
carottes rap<61>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<EFBFBD>u, devra vous pr<70>venir qu'il n'arrive pas <20> hacher un objet si
gros. Et ce message, quoiqu'il sorte aussi bien du hachoir que le steak
hach<EFBFBD>, ne doit pas <20>tre trait<69> de la m<>me fa<66>on <20> sa sortie, et n'est
pas suivi des m<>mes cons<6E>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&nbsp;:</p>
<ul>
<li> une <em>entr<74>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<74>e standard est le clavier, la sortie standard est
l'<27>cran, et la sortie d'erreur est aussi l'<27>cran.</p>
<p> C'est sur le clavier que vous tapez&nbsp;; ce que vous tapez et ce
que renvoient les programmes s'inscrit <20> l'<27>cran&nbsp;; les messages
d'erreur renvoy<6F>s par les programmes s'affichent <20> l'<27>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 <20> fait orienter diff<66>remment
vos programmes.</p>
<p> Par exemple, si vous donnez une vache comme entr<74>e au hachoir, vous
pouvez orienter la sortie vers une imprimante (au lieu de l'<27>cran,
propos<EFBFBD> par d<>faut), et vous imprimerez ainsi du steak hach<63>. </p>
<p>
Ou encore, vous pouvez donner un plant de carottes comme entr<74>e au
programme <code>cueillette</code>, et envoyer la sortie (c'est-<2D>-dire
les carottes cueillies) au programme <code>hachoir</code>.
</p>
<p>
Nous allons <20>tudier successivement&nbsp;:
</p>
<ul>
<li> comment rediriger la sortie d'une commande vers un
fichier&nbsp;;</li>
<li> comment ajouter la sortie d'une commande <20> la fin d'un
fichier&nbsp;;</li>
<li> comment utiliser un fichier comme entr<74>e d'une commande&nbsp;;</li>
<li> comment utiliser la sortie d'une commande comme entr<74>e d'une
autre.</li>
</ul>
<p>
Ces diff<66>rentes configurations esquissent la grammaire d'une utilisation
tr<EFBFBD>s performante des fonctionnalit<69>s du shell&nbsp;; <strong>vous saurez
en effet comment brancher un fichier sur l'entr<74>e ou sur la sortie d'une
commande, et comment brancher la sortie d'une commande sur l'entr<74>e
d'une autre</strong>. Il n'y a pas d'autre combinaison possible.
</p>
<h3>Rediriger la sortie dans un fichier<65>: <code>&gt;</code></h3>
<p>
On peut <em> rediriger</em> la sortie standard d'une commande vers un
fichier (caract<63>re <20>&nbsp;<code>&gt;</code>&nbsp;<3B>). Le r<>sultat de la
commande sera plac<61> dans le fichier au lieu de s'afficher sur l'<27>cran.
Exemple&nbsp;:
</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 <20> l'<27>cran, mais il est plac<61>
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 <20> un fichier<65>: <code>&gt;&gt;</code></h3>
<p> On veut parfois ajouter la sortie d'un programme <20> un fichier, sans
effacer ce qui pr<70>c<EFBFBD>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">
<EFBFBD> chaque fois, le contenu ant<6E>rieur du fichier <code>foo</code> est
<EFBFBD>cras<EFBFBD> par le contenu ult<6C>rieur.
</p>
<p>
Pour <20>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><3E> la suite</em> tout ce que
vous a renvoy<6F> la commande.
</p>
<h3>Rediriger l'entr<74>e<EFBFBD>: <code>&lt;</code></h3>
<p>
On peut aussi rediriger l'entr<74>e standard d'une commande (caract<63>re
<EFBFBD>&nbsp;<code>&lt;</code>&nbsp;<3B>). La commande lira alors le fichier au
lieu du clavier. Exemple&nbsp;:
</p>
<pre><span class="prompt">chaland ~ $</span> elm leroy &lt; foo</pre>
<p class="continue">
envoie par mail <20> Xavier Leroy le r<>sultat de la commande <code>ls -l</code> de
tout <20> l'heure.
</p>
<p>
On peut aussi taper <code>more &lt; foo</code> qui est <20>quivalent <20>
<code>more foo</code> car <code>more</code> sans argument lit son entr<74>e
standard et l'affiche page par page sur le terminal.
</p>
<h3>Connecter la sortie d'une commande sur l'entr<74>e d'une autre<72>:
<code>|</code></h3>
<p>
Il devient rapidement ennuyeux de taper&nbsp;:
</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<72>diaire (<code>foo</code> dans notre
exemple) gr<67>ce <20> un <em>pipe</em> (caract<63>re
<EFBFBD>&nbsp;<code>|</code>&nbsp;<3B>). Un pipe connecte directement la sortie
standard d'une commande sur l'entr<74>e standard d'une autre commande.
Exemple&nbsp;: pour afficher page par page la liste des fichiers du
r<EFBFBD>pertoire courant, faire
</p>
<pre><span class="prompt">chaland ~ $</span> ls -l | less</pre>
<p>
Le pipe, ou tube, est d'un usage tr<74>s courant, et rend beaucoup de
services.
</p>
<h2>Succ<63>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<70>c<EFBFBD>dente a r<>ussi ou <20>chou<6F>.
</p>
<p>
Par exemple, si j'ai un fichier <code>foo</code>, j'obtiens&nbsp;:
</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&nbsp;:
</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>
<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<74>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 <20> 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<EFBFBD> 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<69>es dans les pipe-lines sont:
</p>
<ul>
<li><a href="fichiers.html#less">more</a> (ou <code>less</code>,
bien plus <20>volu<6C>) <20> la fin du pipe-line, affiche le r<>sultat page par page,
pour laisser le temps de le lire.
</li>
<li><a href="divers.html#wc">wc</a> compte le nombre de
caract<EFBFBD>res, de mots et de lignes de son entr<74>e.
</li>
<li><a href="chercher.html#grep">grep</a> cherche dans son
entre les lignes contenant un mot donn<6E>, et les <20>crit sur sa sortie.
</li>
<li><a href="&url.tuteurs;unix/exercices/enchainer.html#syst">sort</a> lit toutes les lignes
de son entr<74>e, les trie, et les <20>crit dans l'ordre sur sa sortie. Par d<>faut
l'ordre est alphab<61>tique.
</li>
<li><a href="fichiers.html#head">tail</a> <20>crit sur sa sortie
les derni<6E>res lignes de son entr<74>e.
</li>
<li><a href="fichiers.html#head">head</a> <20>crit sur sa sortie
les premi<6D>res lignes de son entr<74>e.
</li>
<li><a href="fichiers.html#cat">cat</a> copie plusieurs fichiers
sur sa sortie.
</li>
<li><code>fold</code> coupe les lignes de son
entr<EFBFBD>e <20> 80 caract<63>res et <20>crit le r<>sultat sur sa sortie.
</li>
</ul>
<h3>Exemples</h3>
<pre>cat glop buz &gt; toto</pre>
<p>
Concat<EFBFBD>ne les fichiers <code>glop</code> et <code>buz</code> et place le
r<EFBFBD>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<68>ne
<code>gag</code>.
</p>
<h2>R<>capitulatif</h2>
<p>
La panoplie compl<70>te des redirections est la suivante&nbsp;:
</p>
<ul>
<li><code>&gt;</code><3E>: change la sortie standard de la commande pour la placer
dans un fichier.
</li>
<li><code>&lt;</code><3E>: change l'entr<74>e standard de la commande pour la prendre
dans un fichier.
</li>
<li><code>|</code><3E>: branche la sortie standard de la commande de gauche sur
l'entr<74>e standard de la commande de droite.
</li>
<li><code>&gt;&gt;</code><3E>: change la sortie standard pour l'ajouter <20> la fin
d'un fichier existant.
</li>
<li><code>||</code><3E>: ex<65>cuter la commande suivante si la premi<6D>re a
<EFBFBD>chou<EFBFBD>.
</li>
<li><code>&amp;&amp;</code><3E>: n'ex<65>cuter la commande suivante que si la
premi<EFBFBD>re a r<>ussi.
</li>
</ul>
<p>Vous <20>tes maintenant en mesure de faire ces <a
href="&url.tuteurs;unix/exercices/">exercices</a> pour vous
entra<EFBFBD>ner.</p>
<div class="metainformation">
Bas<EFBFBD> sur un polycopi<70> de Roberto Di Cosmo, Xavier Leroy et Damien Doligez.
Modifications&nbsp;: Nicolas George, Baptiste M<>l<EFBFBD>s.
Derni<EFBFBD>re modification le <date value="$Date: 2005-05-31 11:33:38 $" />.
</div>
</body>
</html>