1208 lines
36 KiB
Text
1208 lines
36 KiB
Text
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
|||
|
<!DOCTYPE html
|
|||
|
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
|
|||
|
"tuteurs://DTD/tml.dtd">
|
|||
|
<html>
|
|||
|
<head>
|
|||
|
<title>Pipes</title>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
|
|||
|
|
|||
|
<h1><em>Pipes</em>, jokers et redirections<6E>: corrig<69>s</h1>
|
|||
|
|
|||
|
<h2><a name="cat">La commande <tt>cat</tt></a></h2>
|
|||
|
<!-- ##########################################################<23>!-->
|
|||
|
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> <strong> <a name="cat1">Comment visualiser deux fichiers l'un apr<70>s
|
|||
|
l'autre <20> l'aide de la commande <tt>cat</tt><3E>? </a> </strong><p>
|
|||
|
|
|||
|
Il suffit de taper les deux noms de fichiers <20> la suite; par exemple, pour
|
|||
|
visualier <tt>bla</tt> puis <tt>blo</tt>, on tape<70>:</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
cat bla blo
|
|||
|
</pre></li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="cat2">Comment faire une copie d'un fichier sans
|
|||
|
utiliser <tt>cp</tt> ni ouvrir d'<27>diteur de texte<74>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
On demande <20> <tt>cat</tt> d'afficher le contenu d'un fichier, puis de placer
|
|||
|
le r<>sultat dans un fichier<65>:</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
cat toto > copie
|
|||
|
</pre></li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="cat3">Utiliser <tt>cat</tt> pour <20>crire un peu de
|
|||
|
texte et mettre le r<>sultat dans un fichier <tt>notes</tt>. </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
On demande <20> <tt>cat</tt> de rediriger sa sortie dans un fichier, puis on n'a
|
|||
|
plus qu'<27> taper le texte et <20> indiquer la fin du texte avec <tt>^D</tt><3E>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">galion ~ $</span><3E>ls
|
|||
|
maitrise.tex
|
|||
|
<span class="prompt">galion ~ $</span><3E>cat > notes
|
|||
|
Faire la bibliographie
|
|||
|
Revoir le chapitre 1.
|
|||
|
^D
|
|||
|
<span class="prompt">galion ~ $</span><3E>ls
|
|||
|
maitrise.tex notes
|
|||
|
<span class="prompt">galion ~ $</span><3E>cat notes
|
|||
|
Faire la bibliographie
|
|||
|
Revoir le chapitre 1.
|
|||
|
<span class="prompt">galion ~ $</span>
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
C'est bien s<>r un moyen un peu spartiate pour <20>crire du texte, mais dans le
|
|||
|
cas de choses tr<74>s courtes dans ce style, ce peut <20>tre plus rapide que de
|
|||
|
lancer un v<>ritable <20>diteur.
|
|||
|
</p></li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="cat4">Quelle diff<66>rence y a-t-il entre </a> </strong>
|
|||
|
|
|||
|
<pre>cat bla blo > blu </pre> <p class="continue"><strong>et</strong></p>
|
|||
|
<pre>cat bla blo >> blu </pre>
|
|||
|
|
|||
|
<p>
|
|||
|
<strong>Que se passe-t-il, pour chaque ligne, selon que le fichier <tt>blu</tt>
|
|||
|
existe ou n'existe pas<61>?</strong></p>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<pre>cat bla blo > blu </pre> <p class="continue">
|
|||
|
concat<EFBFBD>ne les deux fichiers <tt>bla</tt> et
|
|||
|
<tt>blo</tt>, et place le r<>sultat dans un nouveau fichier appel<65>
|
|||
|
<tt>blu</tt>. Si <tt>blu</tt> existe d<>j<EFBFBD>, le shell affiche un message
|
|||
|
d'erreur et ne fait rien.</p>
|
|||
|
|
|||
|
<p>
|
|||
|
<tt>cat bla blo >> blu </tt> place la concat<61>nation de <tt>bla</tt> et
|
|||
|
<tt>blo</tt> <20> la fin d'un fichier <tt>blu</tt> d<>j<EFBFBD> existant. S'il n'existe
|
|||
|
pas, le shell affiche un message d'erreur et en reste l<>, sans cr<63>er de
|
|||
|
fichier <tt>blu</tt>. </p>
|
|||
|
|
|||
|
<p>
|
|||
|
Les deux redirections ne sont donc pas du tout <20>quivalentes, mais leur action
|
|||
|
d<EFBFBD>pend du shell, qui a des options qui modifie leur comportement par d<>faut.
|
|||
|
</p></li>
|
|||
|
|
|||
|
<li> <strong> <a name="cat5">Comment obtenir un fichier <tt>blo</tt> qui
|
|||
|
corresponde <20> un fichier <tt>bla</tt> dont les lignes seraient d<>sormais
|
|||
|
num<EFBFBD>rot<EFBFBD>es<EFBFBD>? </a> </strong>
|
|||
|
|
|||
|
|
|||
|
<p>
|
|||
|
Il faut utiliser l'option <tt>-n</tt> de <tt>cat</tt>. Par exemple<6C>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">galion ~ $</span><3E>cat bla
|
|||
|
Pomme
|
|||
|
Poire
|
|||
|
Prune
|
|||
|
<span class="prompt">galion ~ $</span><3E>cat -n bla > blo
|
|||
|
<span class="prompt">galion ~ $</span><3E>cat blo
|
|||
|
1 Pomme
|
|||
|
2 Poire
|
|||
|
3 Prune
|
|||
|
<span class="prompt">galion ~ $</span>
|
|||
|
</pre></li>
|
|||
|
|
|||
|
</ol>
|
|||
|
|
|||
|
|
|||
|
<h2><a name="jokers">Jokers et expressions r<>guli<6C>res</a></h2>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> <strong> <a name="jokers1">Vous avez chez vous des fichiers appel<65>s
|
|||
|
<tt>essai1</tt>, <tt>essai2</tt>, <tt>essai3</tt> et <tt>essai4</tt>. Comment
|
|||
|
les effacer en une seule ligne de commande<64>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
Il s'agit de donner le nom des fichiers en indiquant qu'ils commencent par
|
|||
|
<tt>essai</tt> et qu'ils finissent par un chiffre. Il y a en fait plusieurs
|
|||
|
fa<EFBFBD>ons de faire<72>:
|
|||
|
</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
|
|||
|
<li> <tt>rm essai[1234]</tt><3E>: les crochets signifient <20>l'un des caract<63>res
|
|||
|
qui se trouvent entre crochets<74>;</li>
|
|||
|
|
|||
|
|
|||
|
<li> <tt>rm essai[1-4]</tt><3E>: c'est le m<>me principe, sauf que l'on indique un
|
|||
|
intervalle au lieu d'<27>crire explicitement les chiffres;</li>
|
|||
|
|
|||
|
|
|||
|
<li> <tt>rm essai?</tt><3E>: le point d'interrogation d<>signe n'importe quel
|
|||
|
caract<EFBFBD>re unique, le point y compris, sauf si le nom du fichier commence par
|
|||
|
un point (<tt>ls<6C>?pine</tt> dans <tt>$HOME</tt> ne vous donnera pas, par
|
|||
|
exemple, la liste des fichiers de configuration de Pine<6E>: <tt>.pinerc</tt>,
|
|||
|
etc).
|
|||
|
|
|||
|
<p>
|
|||
|
Ici, on trouvera tous les fichiers commen<65>ant par <tt>essai</tt>, suivi d'un
|
|||
|
unique caract<63>re qui peut ne pas <20>tre un chiffre.</p>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <tt>rm essai*</tt><3E>: c'est la formulation la plus vague<75>: effacer les
|
|||
|
fichiers dont le nom commence par <tt>essai</tt> suivi de quelque chose,
|
|||
|
c'est-<2D>-dire d'un nombre ind<6E>fini de caract<63>res, ou aucun.</li>
|
|||
|
</ul></li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="jokers2">Dans mon r<>pertoire d'accueil, j'ai un
|
|||
|
certain nombre de fichiers avec un suffixe <tt>.c</tt>. Je d<>sire les
|
|||
|
regrouper dans un r<>pertoire que j'appelerai <tt>C/</tt>. Quelles sont les
|
|||
|
commandes que je dois taper<65>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
On commande par cr<63>er un r<>pertoire <tt>C</tt> avec <tt>mkdir</tt>, puis, avec
|
|||
|
<tt>mv</tt>, on d<>place tous les fichiers ayant un suffixe <tt>.</tt> et
|
|||
|
dont le nom est fait d'une suite de caract<63>res quelconques<65>:
|
|||
|
</p>
|
|||
|
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">galion ~ $</span><3E> ls
|
|||
|
hello* zoinx*
|
|||
|
hello.c zoinx.c
|
|||
|
<span class="prompt">galion ~ $</span><3E> mkdir C
|
|||
|
<span class="prompt">galion ~ $</span><3E> mv *.c C/
|
|||
|
<span class="prompt">galion ~ $</span><3E> ls
|
|||
|
C/ hello* zoinx*
|
|||
|
<span class="prompt">galion ~ $</span><3E> ls C/
|
|||
|
hello.c zoinx.c
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong> <a name="jokers3">Vous d<>sirez regrouper dans un r<>pertoire
|
|||
|
<tt>Rangement</tt> les fichiers dont le nom contient un caract<63>re minuscule
|
|||
|
suivi d'un caract<63>re majuscule. Quelle(s) est/sont la/les commande(s) <20>
|
|||
|
donner<EFBFBD>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
On commence par cr<63>er le r<>pertoire <tt>Rangement</tt> avec <tt>mkdir</tt>.
|
|||
|
Pour d<>signer les noms des fichiers, il faut indiquer la notion de
|
|||
|
<EFBFBD>minuscule<EFBFBD>. On pourrait <20>crire explicitement l'alphabet entre crochets, pour
|
|||
|
dire <20>l'un de ces caract<63>res<65>, puis faire de m<>me avec les majuscules. Mais on
|
|||
|
gagne du temps en utilisant des intervalles (<tt>[a-z]</tt> et
|
|||
|
<tt>[A-Z]</tt>). Le reste du nom du fichier, avant et apr<70>s la minuscule puis
|
|||
|
la majuscule, est ind<6E>fini. On <20>crit donc<6E>:
|
|||
|
</p>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">galion ~ $</span><3E>mkdir Rangement
|
|||
|
<span class="prompt">galion ~ $</span><3E>mv *[a-z][A-Z]* Rangement/
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="jokers4">M<>me chose avec les fichiers dont le nom
|
|||
|
contient trois voyelles <20> la suite. </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
Le principe est le m<>me, sauf que l'on indique explicitement les voyelles
|
|||
|
entre crochets<74>:
|
|||
|
</p>
|
|||
|
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">galion ~ $</span><3E>mkdir Rangement
|
|||
|
<span class="prompt">galion ~ $</span><3E>mv *[aeiou][aeiou][aeiou]* Rangement/
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong> <a name="jokers5">En utilisant <tt>ls</tt> et <tt>grep</tt>,
|
|||
|
affichez la liste des fichiers dans <tt>/bin</tt> dont le nom correspond <20> un
|
|||
|
motif donn<6E>. </a>
|
|||
|
</strong>
|
|||
|
<p>
|
|||
|
On peut proc<6F>der de deux fa<66>ons<6E>: utiliser <tt>ls</tt> seul et des jokers, ou
|
|||
|
rediriger <tt>ls</tt> dans <tt>grep</tt> et utiliser les expressions
|
|||
|
r<EFBFBD>guli<EFBFBD>res de <tt>grep</tt>.
|
|||
|
</p>
|
|||
|
|
|||
|
<div class="attention">
|
|||
|
<h1>&icone.attention;<3B>Attention<6F>&icone.attention;</h1>
|
|||
|
<p>Dans la suite du corrig<69>, on suppose que l'on se trouve d<>j<EFBFBD> dans
|
|||
|
<tt>/bin/</tt>.</p>
|
|||
|
|
|||
|
<p>On met des apostrophes autour des expressions de
|
|||
|
<tt>grep</tt> pour les prot<6F>ger contre le shell. Enfin, on ne d<>taille pas les
|
|||
|
expressions r<>guli<6C>res; <20> noter ces points importants <20> propos de
|
|||
|
<tt>grep</tt><3E>:</p>
|
|||
|
|
|||
|
|
|||
|
<ul>
|
|||
|
|
|||
|
<li> Le chapeau (<tt>^</tt>) en d<>but d'expression d<>signe le d<>but de la
|
|||
|
ligne;</li>
|
|||
|
|
|||
|
<li> Le dollar en fin d'expression d<>signe la fin de la ligne;</li>
|
|||
|
|
|||
|
<li> Le point d<>signe n'importe quel caract<63>re; </li>
|
|||
|
|
|||
|
<li> L'<27>toile signifie <20>z<EFBFBD>ro ou plus de fois le caract<63>re qui pr<70>c<EFBFBD>de<64>; c'est
|
|||
|
un multiplicateur;</li>
|
|||
|
|
|||
|
<li> Comme avec les jokers du shell, <tt>[^m]</tt> veut dire <20>sauf le
|
|||
|
caract<EFBFBD>re m<>.</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
|
|||
|
<p>
|
|||
|
On constate que <tt>grep</tt> est plus complexe mais bien plus puissant que
|
|||
|
les jokers du shell.
|
|||
|
</p>
|
|||
|
|
|||
|
|
|||
|
<table class="tableau">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<tr>
|
|||
|
|
|||
|
<td> </td>
|
|||
|
<td> Avec <tt>ls</tt> seul </td>
|
|||
|
<td> Avec <tt>ls</tt> et <tt>grep</tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
|
|||
|
<td> Commence par <20>a<EFBFBD> et dont la deuxi<78>me lettre est <20>s<EFBFBD> ou <20>t<EFBFBD> </td>
|
|||
|
<td> <tt> ls a[st]* </tt> </td>
|
|||
|
<td> <tt> ls | grep '^a[st].*' </tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Contient <20>un<75> et se termine par <20>t<EFBFBD> </td>
|
|||
|
<td> <tt>ls *un*t </tt> </td>
|
|||
|
<td> <tt>ls | grep '.*un.*t$' </tt> </td>
|
|||
|
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Contient <20>gre<72> ou <20>st<73> </td>
|
|||
|
<td> <tt> ls *(gre|st)* </tt> </td>
|
|||
|
<td> <tt> ls | grep '\(gre\|st\)' </tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Contient exactement deux lettres <20>m<EFBFBD> </td>
|
|||
|
<td> </td>
|
|||
|
<td> <tt>ls | grep '[^m]*m[^m]*m[^m]*' </tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Contient au moins deux lettres <20>m<EFBFBD> </td>
|
|||
|
<td> </td>
|
|||
|
<td> <tt>ls | grep '.*m.*m.*' </tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Contient au moins quatre caract<63>res et aucun chiffre </td>
|
|||
|
<td> </td>
|
|||
|
<td> <tt>ls | grep '^[^0-9]\{4,\}$' </tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Est constitu<74> de deux lettres exactement </td>
|
|||
|
<td> <tt>ls<6C>?? </tt> </td>
|
|||
|
<td> <tt>ls | grep '^..$' </tt> </td>
|
|||
|
<td> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
|
|||
|
<tr>
|
|||
|
<td> Commence et finit par un chiffre </td>
|
|||
|
<td> <tt>ls [0-9]*[0-9] </tt> </td>
|
|||
|
<td> <tt>ls | grep '^[0-9].*[0-9]$' </tt> </td>
|
|||
|
</tr>
|
|||
|
|
|||
|
</table>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong> <a name="jokers6"> Comment <20>liminer les lignes vides dans un
|
|||
|
fichier<EFBFBD>? Comment <20>liminer les lignes ne contenant que des blancs<63>?
|
|||
|
Comment <20>liminer toutes les lignes blanches<65>?</a> </strong>
|
|||
|
|
|||
|
<p class="continue">
|
|||
|
<a name="precision">Une ligne vide</a> est diff<66>rente d'une ligne ne contenant
|
|||
|
que des blancs, c'est-<2D>-dire des espaces ou des tabulations, m<>me si pour un
|
|||
|
oeil humain cela revient au m<>me. La commande de recherche sera diff<66>rente
|
|||
|
selon le cas<61>:
|
|||
|
</p>
|
|||
|
<ul>
|
|||
|
|
|||
|
<li> <strong>Lignes vides</strong><3E>: c'est <20>rien entre le d<>but et la fin de
|
|||
|
la ligne<6E>; on <20>crit donc<6E>:
|
|||
|
<pre>grep '^$' <em>fichier</em></pre></li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong>Lignes ne contenant que des blancs</strong><3E>: on utilise une
|
|||
|
classe de caract<63>re pr<70>existante<74>: <tt>[:space:]</tt>. On <20>crit donc<6E>:
|
|||
|
<pre>grep '^[[:space:]]$' <em>fichier</em></pre>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>
|
|||
|
Pour <20>liminer toutes les lignes blanches pour un oeil humain, on combine les
|
|||
|
deux expressions et on utilise l'option <tt>-v</tt> qui inverse le sens de la
|
|||
|
recherche. On n'a plus qu'<27> rediriger la sortie dans un fichier. On <20>crit
|
|||
|
donc<EFBFBD>: </p>
|
|||
|
|
|||
|
<pre>grep -v '\(^[[:space:]]$\|^$\)' fichier1 > fichier2 </pre>
|
|||
|
<p class="continue">
|
|||
|
en rempla<6C>ant <20>ventuellement le motif par <tt>'^$'</tt> ou
|
|||
|
<tt>^[[:space:]]$'</tt> selon que l'on veut <20>ter les lignes vides ou les
|
|||
|
lignes contenant des blancs.
|
|||
|
</p></li>
|
|||
|
</ol>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<h2><a name="germinal">Exercices sur <em>Germinal</em></a></h2>
|
|||
|
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li><a name="germinal1"> <strong>Combien de fois le mot <20>mine<6E> appara<72>t dans
|
|||
|
chaque chapitre de la premi<6D>re partie de <em>Germinal</em><3E>?</strong></a> <p>
|
|||
|
|
|||
|
|
|||
|
On cherche la cha<68>ne de caract<63>re <20>mine<6E>, qui soit un mot, <20>ventuellement
|
|||
|
suivi d'un <20>s<EFBFBD>. On va donc d<>signer le d<>but du mot avec le symbole
|
|||
|
<tt>\<</tt>, la fin du mot avec le symbole <tt>\></tt>, et le <20>s<EFBFBD>
|
|||
|
optionnel avec le point d'interrogation. On veut aussi faire appara<72>tre le
|
|||
|
nombre d'occurences du mot, dans chaque fichier du r<>pertoire <tt>zola</tt>,
|
|||
|
avec l'option <tt>-c</tt> de <tt>grep</tt>. </p>
|
|||
|
|
|||
|
<p>
|
|||
|
Les noms des fichiers de <em>Germinal</em> sont de la forme
|
|||
|
<tt>zola1.txt</tt>, de 1 <20> 6. Pour chercher dans tous les fichiers de cette
|
|||
|
sorte, on peut <20>crire, au choix (attention <20> ne pas confondre les
|
|||
|
<em>wildcards</em> du shell avec les expressions r<>guli<6C>res de grep).
|
|||
|
</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
|
|||
|
<li> <tt>zola*.txt</tt> (un ou plusieurs caract<63>res entre <tt>zola</tt> et
|
|||
|
<tt>.txt</tt>).</li>
|
|||
|
|
|||
|
<li> <tt>*.txt</tt> (tous les fichiers <tt>.txt</tt> du r<>pertoire, mais il
|
|||
|
pourrait y en avoir d'autres que <tt>zola*.txt</tt>).</li>
|
|||
|
|
|||
|
<li> <tt>zola?.txt</tt> (un seul caract<63>re entre <tt>zola</tt> et le
|
|||
|
suffixe).</li>
|
|||
|
|
|||
|
<li> <tt>zola[1-6].txt</tt> (un chiffre entre 1 et 6 inclus entre
|
|||
|
<tt>zola</tt> et le suffixe).</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>
|
|||
|
On peut donc <20>crire<72>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>grep -c '\<mines?\>' *.txt</pre>
|
|||
|
|
|||
|
|
|||
|
<p>Et on obtient<6E>:</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
zola1.txt:5
|
|||
|
zola2.txt:0
|
|||
|
zola3.txt:3
|
|||
|
zola4.txt:3
|
|||
|
zola5.txt:1
|
|||
|
zola6.txt:2
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Attention<EFBFBD>: les chiffres indiqu<71>s correspondent au nombre de lignes o<> figure
|
|||
|
le mot <20>mine<6E>, mais pas au nombre r<>el d'occurences du mot. Pour un mot pr<70>cis
|
|||
|
comme celui-ci, la marge d'erreur est faible, mais si vous cherchez un article
|
|||
|
d<EFBFBD>fini, par exemple, cette m<>thode est insuffisante. C'est l<> qu'un langage
|
|||
|
comme Perl est tr<74>s utile.
|
|||
|
</p></li>
|
|||
|
|
|||
|
|
|||
|
<li><a name="germinal2"> <strong>Combien y a-t-il de lignes blanches dans
|
|||
|
<tt>zola1.txt</tt><3E>? </strong> </a> <p>
|
|||
|
<a name="blanche"> Une ligne blanche, </a> c'est rien entre un d<>but de ligne
|
|||
|
et une fin de ligne, ou alors une ligne ne contenant que des espaces et des
|
|||
|
tabulations. On va donc chercher toutes les lignes correspondant <20> ce sch<63>ma
|
|||
|
(voir <a href="#precision">plus haut</a> pour ces questions de d<>finitions).
|
|||
|
Comme il y a deux motifs <20> chercher, on utilise l'expression r<>guli<6C>re qui
|
|||
|
permet de chercher un motif ou un autre<72>: </p>
|
|||
|
|
|||
|
<pre>\(<em>motif1</em>\|<em>motif2</em>\)</pre>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<p>
|
|||
|
La commande <20> taper est<73>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>grep '\(^[[:space:]]$\|^$\)' zola1.txt</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Ensuite, on veut compter le nombre de lignes ainsi produites par
|
|||
|
<tt>grep</tt>, avec la commande <tt>wc</tt> (<em>word count</em>); on va
|
|||
|
utiliser l'option <tt>-l</tt> (<em>lines</em>, lignes). On tape donc<6E>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>grep '\(^[[:space:]]$\|^$\)' zola1.txt | wc -l</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Et on obtient <20>81<38>. Bien <20>videmment, on aurait pu se rappeler que l'option
|
|||
|
<tt>-c</tt> de <tt>grep</tt> donne le nombre de lignes matchant la cha<68>ne
|
|||
|
recherch<EFBFBD>e, et obtenir le m<>me r<>sultat en ne lan<61>ant qu'un seul processus...
|
|||
|
</p></li>
|
|||
|
|
|||
|
</ol>
|
|||
|
|
|||
|
<h2><a name="headtail"><tt>head</tt> et <tt>tail</tt></a></h2>
|
|||
|
<!-- ####################################################<23>!-->
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="headtail1">Affichez les 15 premi<6D>res lignes du fichier
|
|||
|
<tt>/etc/hosts</tt>, les 15 derni<6E>res lignes, toutes les lignes <20> partir de la
|
|||
|
quinzi<EFBFBD>me, les lignes 15 <20> 20. </a> </strong> <p>
|
|||
|
|
|||
|
<strong><3E> propos du fichier <tt>/etc/hosts</tt></strong><3E>: les ordinateurs sur
|
|||
|
l'Internet sont d<>sign<67>s par une adresse IP, constitu<74>e de 4 nombres entre 0
|
|||
|
et 255 s<>par<61>s par des points. C'est cette adresse IP qui permet <20> un
|
|||
|
ordinateur d'envoyer un message (datagramme IP) <20> un autre.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Cependant, m<>moriser les adresses IP n'est pas commode pour un humain. Pour
|
|||
|
cette raison, les ordinateurs ont aussi un <20>nom<6F>, constitu<74> d'un nombre
|
|||
|
variable de composantes s<>par<61>es par des points (par exemple,
|
|||
|
<tt>research.att.com</tt>).
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Le m<>canisme de conversion d'un nom en adresse IP (ou le m<>canisme inverse)
|
|||
|
s'appelle la <20>r<EFBFBD>solution de noms<6D>. Elle se fait normalement par
|
|||
|
l'interm<72>diaire de <em>nameservers</em>, ordinateurs sur lequel tourne le
|
|||
|
programme BIND, qui se chargent de r<>pondre aux questions de r<>solution de
|
|||
|
noms.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Cependant, pour certaines machines tr<74>s commun<75>ment acc<63>d<EFBFBD>es depuis un
|
|||
|
ordinateur donn<6E> (par exemple, les machines de la m<>me salle) ou bien
|
|||
|
pour <20>viter d'avoir <20> configurer un nameserver, on pr<70>f<EFBFBD>re parfois
|
|||
|
utiliser le fichier <tt>/etc/hosts</tt><3E>: celui-ci d<>finit un certain nombre
|
|||
|
de conversions nom -> adresse IP qui seront consult<6C>es avant les
|
|||
|
<em>nameservers</em>.</p>
|
|||
|
|
|||
|
<p>
|
|||
|
La biblioth<74>que qui se charge de faire la traduction, et qui consulte d'abord
|
|||
|
le <tt>/etc/hosts</tt> puis les <em>nameservers</em>, s'appelle la
|
|||
|
<tt>libresolv</tt>.</p>
|
|||
|
|
|||
|
|
|||
|
<ul>
|
|||
|
|
|||
|
<li> Afficher les 15 premi<6D>res lignes de <tt>/etc/hosts</tt><3E>:
|
|||
|
<pre>head -15 /etc/hosts</pre></li>
|
|||
|
|
|||
|
<li> Afficher les 15 derni<6E>res lignes de <tt>/etc/hosts</tt><3E>:
|
|||
|
<pre>tail -15 /etc/hosts</pre></li>
|
|||
|
|
|||
|
<li> Afficher toutes les lignes <20> partir de la quinzi<7A>me<6D>:
|
|||
|
<pre>tail +15 /etc/hosts</pre></li>
|
|||
|
|
|||
|
<li> Affichez les lignes 15 <20> 20<32>:
|
|||
|
<pre>head -20 /etc/hosts | tail -6 </pre></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li><a name="headtail2"> <strong>R<>cup<75>rer les lignes 5 <20> 9 d'un fichier de 12
|
|||
|
lignes</strong> </a> <p>
|
|||
|
|
|||
|
|
|||
|
Il y a deux solutions<6E>:
|
|||
|
</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> Prendre les neuf premi<6D>res lignes, et n'en garder que les cinq derni<6E>res
|
|||
|
(de 5 <20> 9 inclus)<29>:
|
|||
|
|
|||
|
<pre>head -9 fichier | tail -5</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> Prendre les 8 derni<6E>res lignes (de 5 <20> 12 inclus) et n'en garder que
|
|||
|
les 5 premi<6D>res<65>:
|
|||
|
<pre>tail -8 fichier | head -5</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
</ol></li>
|
|||
|
|
|||
|
<li> <strong> <a name="headtail4">Comment afficher la cinqui<75>me ligne d'un
|
|||
|
fichier<EFBFBD>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
On utilise la commande <tt>head</tt> pour extraire les cinq premi<6D>res
|
|||
|
lignes du fichier, puis la commande <tt>tail</tt> pour ne conserver que la
|
|||
|
derni<EFBFBD>re des cinq<6E>: </p>
|
|||
|
|
|||
|
|
|||
|
<pre> head -5 fichier | tail -1 </pre>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
|
|||
|
<h2><a name="syst">Filtres et redirections</a></h2>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="syst1">Cr<43>ez un fichier dont chaque ligne commence
|
|||
|
par un chiffre, suivi d'un slash (<tt>/</tt>), puis d'un ou plusieurs mots.
|
|||
|
</a> </strong>
|
|||
|
<p>
|
|||
|
C'est la commande <tt>sort</tt> qui permet de trier des fichiers selon un
|
|||
|
ordre donn<6E>.</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> <strong>Affichez les lignes de ce fichier tri<72>es en ordre croissant,
|
|||
|
suivant le nombre plac<61> en d<>but de ligne</strong> <p>
|
|||
|
<tt>sort</tt> sans option trie automatiquement en fonction du premier caract<63>re,
|
|||
|
par ordre alphab<61>tique si c'est une lettre, par ordre croissant si ce sont des
|
|||
|
chiffres. Il suffit donc de taper<65>:
|
|||
|
</p>
|
|||
|
<pre>sort fichier</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong><3E>liminez de chaque ligne le chiffre et le caract<63>re
|
|||
|
<EFBFBD><tt>/</tt><3E></strong>. <p> Pour cela, sans utiliser d'<27>diteur, on peut
|
|||
|
utiliser la commande <tt>cut</tt>, qui <20>limine des champs dans une ligne. Par
|
|||
|
d<EFBFBD>faut, le s<>parateur de champs est une tabulation. Ici, on peut demander <20>
|
|||
|
<tt>cut</tt> de consid<69>rer le slash comme un s<>parateur de champs (option
|
|||
|
<tt>-d</tt>, <20>d<EFBFBD>limiteur<75>), et de ne conserver que le deuxi<78>me champ du
|
|||
|
fichier (option <tt>-f</tt>, <em>field</em>). On redirige ensuite la sortie
|
|||
|
dans un autre fichier<65>: </p>
|
|||
|
|
|||
|
<pre> cut -d/ -f2 fichier > fichier2</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li> <strong>Triez ces lignes par ordre alphab<61>tique inverse</strong>.
|
|||
|
C'est l'option <tt>-r</tt> (<em>reverse</em>) de <tt>sort</tt> qui inverse le
|
|||
|
r<EFBFBD>sultat de la comparaison. Par d<>faut, <tt>sort</tt> trie par ordre
|
|||
|
alphab<EFBFBD>tique, il suffit donc de taper<65>:
|
|||
|
|
|||
|
<pre>sort -r fichier2</pre></li>
|
|||
|
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
|
|||
|
<li><a name="syst2"> <strong>Combien de fichiers de configuration avez-vous
|
|||
|
?</strong> </a>
|
|||
|
|
|||
|
<p>
|
|||
|
La r<>ponse n'est pas simple, car vous avez <20>galement des r<>pertoires de
|
|||
|
configuration, comme <tt>.netscape/</tt> qui contient entre autres vos
|
|||
|
marque-pages (<tt>bookmarks.html</tt>), vos pr<70>f<EFBFBD>rences
|
|||
|
(<tt>preferences</tt>), etc. On va compter le nombre de fichiers commen<65>ant
|
|||
|
par un point situ<74>s dans votre r<>pertoire principal, en <20>liminant les copies
|
|||
|
de sauvegarde (qui finissent par un tilde). Il y a plusieurs mani<6E>res de
|
|||
|
proc<EFBFBD>der.</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> <strong>ls, grep, tr, cut</strong> <p>
|
|||
|
On peut penser <20> une solution complexe et bien lourde utilisant toutes ces
|
|||
|
commandes, ce qui permet de les apprendre plus qu'autre chose... On affiche
|
|||
|
une liste longue avec l'ensemble des fichiers (<tt>ls -la</tt>) puis qui
|
|||
|
<EFBFBD>limine tous les r<>pertoires et les liens avec <tt>grep</tt> en ne gardant que
|
|||
|
les lignes qui commencent par un tiret<65>: </p>
|
|||
|
|
|||
|
<pre>ls -al | grep '^-'</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Ensuite, on utilise <tt>tr</tt> pour ne conserver qu'un seul espace entre
|
|||
|
chaque champ de la liste, en utilisant l'option <tt>-s</tt> (<em>squeeze</em>)
|
|||
|
qui remplace par une seule occurence la r<>p<EFBFBD>tition d'un caract<63>re sp<73>cifi<66>; on
|
|||
|
met des apostrophes autour de l'espace pour qu'il soit compris comme tel et
|
|||
|
non comme un simple espace<63>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>tr -s ' ' </pre>
|
|||
|
|
|||
|
<p>
|
|||
|
On utilise <tt>cut</tt> pour conserver le dernier champ avec les noms de
|
|||
|
fichiers (en l'occurence le neuvi<76>me champ), en indiquant que l'espace sert de
|
|||
|
d<EFBFBD>limiteur de champ<6D>: </p>
|
|||
|
|
|||
|
<pre> cut -d' ' -f9 </pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Enfin, on demande <20> <tt>grep</tt> de ne retenir que les fichiers commen<65>ant
|
|||
|
par un point, et ne finissant pas par un tilde, et on les comptel'option
|
|||
|
<tt>-c</tt> de <tt>grep</tt>. Cela donne pour finir<69>: </p>
|
|||
|
|
|||
|
<pre> ls -al | grep '^-' | tr -s ' ' | cut -d' ' -f 9 | grep -c '^\..*[^~]$'
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Mais que de tourments pour si peu...<2E>:-)
|
|||
|
</p></li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong>ls et grep </strong> <p> Il y a plus simple... On demande <20>
|
|||
|
<tt>ls</tt> une liste des fichiers commen<65>ant par un point (avec l'option
|
|||
|
<tt>-d</tt> pour ne pas descendre dans les r<>pertoires de configuration), on
|
|||
|
ne garde que les lignes ne finissant pas par un <tt>/</tt> ou un tilde, et on
|
|||
|
compte<EFBFBD>: </p>
|
|||
|
|
|||
|
<pre>ls -ad .* | grep -vc '\(~\|/\)$' </pre>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong>find</strong>
|
|||
|
<p>
|
|||
|
On demande <20> <tt>find</tt> de chercher dans le r<>pertoire courant
|
|||
|
(<tt>.</tt>), sans descendre dans l'arborescence (<tt>-maxdepth 1</tt>), tous
|
|||
|
les fichiers normaux (<tt>-type f</tt><3E>: <em>file</em>), dont le nom commence
|
|||
|
par un point (<tt>-name '.*'</tt>). On les compte ensuite avec <tt>wc</tt><3E>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>find . -maxdepth 1 -name '.*' -type f | wc -l</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Cette solution est pr<70>f<EFBFBD>rable car elle ne lance que deux processus et non pas
|
|||
|
au moins cinq comme la pr<70>c<EFBFBD>dente.
|
|||
|
</p></li>
|
|||
|
|
|||
|
</ol>
|
|||
|
</li>
|
|||
|
|
|||
|
<li><a name="syst3"> <strong>Combien de r<>pertoires de configuration avez-vous
|
|||
|
?</strong> </a> <p>
|
|||
|
|
|||
|
|
|||
|
Il y a deux solutions, l'une faisant appel <20> <tt>ls</tt> et <tt>grep</tt>,
|
|||
|
l'autre faisant appel <20> <tt>find</tt>.
|
|||
|
</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> <strong><tt>ls</tt> et <tt>grep</tt></strong>
|
|||
|
|
|||
|
<p>
|
|||
|
Le principe est le m<>me que dans l'exercice pr<70>c<EFBFBD>dent. La diff<66>rence est que
|
|||
|
<tt>grep</tt> va chercher les lignes qui commencent par un point
|
|||
|
<strong>et</strong> finissent par un slash. Cela se fait de la mani<6E>re
|
|||
|
suivante<EFBFBD>: </p>
|
|||
|
|
|||
|
<pre>grep '^\..*/$'</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
<tt>.*</tt> signifie <20>n'importe quel caract<63>re (point) r<>p<EFBFBD>t<EFBFBD> z<>ro ou
|
|||
|
plusieurs fois (<28>toile)<29>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
On tape donc<6E>: </p>
|
|||
|
|
|||
|
<pre>ls -ad .* | grep '^\..*/$' | wc -l</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
On part ici du principe que vous avez un alias de <tt>ls</tt> sur <tt>ls
|
|||
|
-F</tt> (qui met un slash apr<70>s les noms de r<>pertoires, une <20>toile apr<70>s les
|
|||
|
noms d'ex<65>cutables et une arobase apr<70>s les noms de liens). Si ce n'est pas le
|
|||
|
cas, ajoutez-le dans un fichier <tt>.alias</tt> ou tapez <tt>ls -lF</tt>.
|
|||
|
</p></li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong><tt>find</tt></strong>
|
|||
|
|
|||
|
<p>
|
|||
|
On demande <20> <tt>find</tt> de chercher tous les fichiers de type <20>r<EFBFBD>pertoire<72>
|
|||
|
(<tt>-type d</tt><3E>: <em>directory</em>), et dont le nom commence par un point
|
|||
|
(<tt>-name '.*'</tt>, les quotes servant <20> prot<6F>ger du shell le contenu de
|
|||
|
l'expression), dans descendre dans l'arborescence.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
On tape donc<6E>: </p>
|
|||
|
|
|||
|
<pre>find . -maxdepth 1 type d -name '.*' | wc -l</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>
|
|||
|
Il y a une inexactitude dans le r<>sultat<61>: <tt>find</tt> compte aussi
|
|||
|
<tt>./</tt> dans le r<>sultat.
|
|||
|
</p></li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="syst4">Comment mettre dans un fichier la liste de
|
|||
|
tous les fichiers de l'arborescence <20> partir du r<>pertoire courant<6E>?
|
|||
|
</a> </strong> <p>
|
|||
|
|
|||
|
C'est l'option <tt>-R</tt> de <tt>ls</tt> qui permet d'afficher
|
|||
|
r<EFBFBD>cursivement le contenu d'un r<>pertoire et de ses sous-r<>pertoires (<28> ne
|
|||
|
pas confondre avec <tt>-r</tt> qui inverse le tri). Pour rediriger la
|
|||
|
sortie d'une commande dans un fichier, on utilise le caract<63>re
|
|||
|
<tt>></tt>. Pour mettre la liste de tous les fichiers de l'arborescence
|
|||
|
dans un fichier <tt>toto</tt>, il faut donc taper<65>: </p>
|
|||
|
|
|||
|
<pre> ls -R > toto </pre>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li><a name="syst5"> <strong>Cr<43>ez un fichier <tt>liste</tt> contenant la
|
|||
|
liste de tous vos fichiers, avec leur taille, leurs droits, etc</strong></a>
|
|||
|
<p>
|
|||
|
Il va s'agir de faire une liste r<>cursive de l'ensemble de votre compte
|
|||
|
(option <tt>-R</tt> de <tt>ls</tt>), incluant les fichiers de configuration
|
|||
|
(option <tt>-a</tt>) et les renseignements donn<6E>s par l'option <tt>-l</tt>.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
De la longue liste obtenue, on ne veut retenir que les fichiers, dont les
|
|||
|
droits commencent par un tiret (un <tt>d</tt> identifie les r<>pertoires). On
|
|||
|
va donc demander <20> <tt>grep</tt> de chercher toutes les lignes commen<65>ant par
|
|||
|
un tiret.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Enfin, on va placer le r<>sultat dans un fichier appel<65> <tt>liste</tt>. On tape
|
|||
|
donc<EFBFBD>: </p>
|
|||
|
|
|||
|
<pre>ls -alR | grep '^-' > liste</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong> <a name="syst6">Comment afficher uniquement les fichiers
|
|||
|
du r<>pertoire courant qui sont des liens symboliques<65>? </a> </strong>
|
|||
|
<p>
|
|||
|
|
|||
|
L'option <tt>-l</tt> de <tt>ls</tt> donne une liste longue des fichiers,
|
|||
|
incluant les droits et le type des fichiers, identifi<66>s par une
|
|||
|
lettre<EFBFBD>: rien pour un fichier, <20>d<EFBFBD> pour un r<>pertoire
|
|||
|
(<em>directory</em>), <20>l<EFBFBD> pour un lien (<em>link</em>); par exemple<6C>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
drwxr-xr-x 2 emilia users 1024 mai 10 02:27 www/
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Pour obtenir la liste des fichiers du r<>pertoire courant qui sont des liens
|
|||
|
symboliques, il suffit donc d'afficher cette liste longue et de ne retenir
|
|||
|
que les lignes qui commencent par un <20>l<EFBFBD>, gr<67>ce <20> la commande
|
|||
|
<tt>grep</tt>. On utilise une expression r<>guli<6C>re pour cela<6C>: le
|
|||
|
chapeau (<tt>^</tt>) d<>signe le d<>but de la ligne, et l'ensemble de
|
|||
|
l'expression est plac<61>e entre apostrophes pour qu'elle ne soit pas
|
|||
|
interpr<EFBFBD>t<EFBFBD>e par le shell. On tape donc<6E>:
|
|||
|
</p>
|
|||
|
|
|||
|
|
|||
|
<pre>ls -l | grep '^l' </pre>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li><a name="syst7"> <strong>Combien de lignes contiennent le mot
|
|||
|
<EFBFBD><em>file</em><3E> dans la page de man de <tt>less</tt><3E>? </strong> </a> <p>
|
|||
|
|
|||
|
|
|||
|
Il faut lancer le man de <tt>less</tt>, et ensuite chercher dedans le nombre
|
|||
|
de lignes contenant le mot <tt>file</tt> (<28>fichier<65> en anglais), avec
|
|||
|
<tt>grep</tt>. C'est l'option <tt>-c</tt> (<em>count</em>) de <tt>grep</tt>
|
|||
|
qui va servir.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Finalement, on <20>crit<69>: </p>
|
|||
|
|
|||
|
<pre>man less | grep -c file</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
Et on obtient 205. C'est le nombre de lignes contenant au moins une fois la
|
|||
|
cha<EFBFBD>ne de caract<63>res <em>file</em>, mais pas le nombre d'occurences du mot
|
|||
|
dans le fichier<65>: il pourrait y avoir plusieurs fois <em>file</em> sur la m<>me
|
|||
|
ligne. On atteint l<> encore la limite de ce que sait faire <tt>grep</tt>.
|
|||
|
</p></li>
|
|||
|
|
|||
|
<li><a name="syst8"> <strong>Quels sont les dix plus gros fichiers de
|
|||
|
<tt>/usr/bin/</tt><3E>?</strong> </a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<p>
|
|||
|
Il faut d'abord faire une liste des fichiers avec leurs tailles (option
|
|||
|
<tt>-l</tt> de <tt>ls</tt>. Ensuite, il faut trier ces lignes en fonction de
|
|||
|
la taille, avec la commande <tt>sort</tt>. Une ligne est de la forme
|
|||
|
suivante<EFBFBD>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
-rwxr-xr-x 1 root staff 5872 Jan 21 1994 /usr/bin/rm*
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
C'est le cinqui<75>me champ, celui de la taille, qui nous int<6E>resse. La
|
|||
|
num<EFBFBD>rotation commen<65>ant <20> 0 (comme les <20>tages), pour indiquer le cinqui<75>me
|
|||
|
champ on <20>crit <tt>+4</tt>. Ensuite, on veut que le tri se fasse selon un
|
|||
|
crit<EFBFBD>re num<75>rique (option <tt>-n</tt>) et <20> l'envers, en commen<65>ant par les
|
|||
|
plus grandes valeurs (option <tt>-r</tt>, <em>reverse</em>).
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Pour finir, on veut les dix premi<6D>res lignes du r<>sultat. On les s<>lectionne
|
|||
|
avec la commande <tt>head</tt>; par d<>faut, elle prend les dix premi<6D>res
|
|||
|
lignes d'un fichier, il n'est donc pas n<>cessaire de pr<70>ciser le nombre de
|
|||
|
lignes voulues. Finalement, on <20>crit<69>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>ls -l /usr/bin | sort -nr +4 | head</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong> <a name="syst9">Pour chaque ligne du fichier
|
|||
|
<tt>/etc/hosts</tt>, affichez<65>: </a> </strong>
|
|||
|
|
|||
|
<ul>
|
|||
|
|
|||
|
<li> Le cinqui<75>me caract<63>re;</li>
|
|||
|
|
|||
|
<li> Les caract<63>res 5 <20> 10, et le treizi<7A>me;</li>
|
|||
|
|
|||
|
<li> Tous les caract<63>res <20> partir du quinzi<7A>me.</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Une mani<6E>re de r<>soudre cet exercice consiste <20> utiliser le programme
|
|||
|
<code>sed</code> qui sert <20> manipuler du texte.</p>
|
|||
|
|
|||
|
<p>Nous allons utiliser la commande <code>s</code> de <code>sed</code>.
|
|||
|
Sa syntaxe est la</p> <pre>s/<em>regexp</em>/<em>remplacement</em>/</pre> <p
|
|||
|
class="continue">o<> <em>regexp</em> est une <a
|
|||
|
href="&url.tuteurs;unix/exercices/grep.html">expression r<>guli<6C>re</a> et
|
|||
|
<em>remplacement</em> un cha<68>ne devant la remplacer.</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Pour afficher le cinqui<75>me caract<63>re de chaque ligne, on peut faire
|
|||
|
ceci<EFBFBD>:
|
|||
|
<pre>
|
|||
|
<span class="prompt">clipper ~ $</span><3E>cat /etc/hosts | sed -e "s/^.\{4\}\(.\).*/\1/"
|
|||
|
</pre>
|
|||
|
<p class="continue">Le <code>"^.\{4\}"</code> du d<>but sert <20> filtrer les
|
|||
|
4 premiers caract<63>res de chaque ligne. Ensuite, <code>\(.\)</code> filtre
|
|||
|
n'importe quel caract<63>re, le fait de mettre des parenth<74>ses enregistre le
|
|||
|
caract<EFBFBD>re en question dans une variable que l'on peut utiliser dans
|
|||
|
la cha<68>ne de remplacement avec <code>"\1"</code>. Ensuite,
|
|||
|
<code>.*</code> filtre le reste de la ligne.</p></li>
|
|||
|
<li>
|
|||
|
Sur le m<>me principe, pour afficher les caract<63>res 5 <20> 10 et le treizi<7A>me :
|
|||
|
<pre>
|
|||
|
<span class="prompt">clipper ~ $</span><3E>cat /etc/hosts | sed -e "s/^.\{4\}\(.\{6\}\)..\(.\).*/\1 \2/"
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
Et enfin, pour afficher tous les caract<63>res <20> partir du quinzi<7A>me<6D>:
|
|||
|
<pre>
|
|||
|
<span class="prompt">clipper ~ $</span><3E>cat /etc/hosts | sed -e "s/^.\{14\}//"
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</ol>
|
|||
|
|
|||
|
<h2><a name="yp">Exercices sur les pages jaunes</a></h2>
|
|||
|
<!-- ####################################################<23>!-->
|
|||
|
|
|||
|
<p>
|
|||
|
Les pages jaunes (<em>yellow pages</em>) sont un syst<73>me qui centralise
|
|||
|
certaines bases de donn<6E>es communes <20> toutes les machines du syst<73>me (logins
|
|||
|
et noms utilisateurs, mots de passes, groupes d'utilisateurs, noms et adresses
|
|||
|
des autres machines sur le r<>seau) sur un petit nombre de serveurs redondants;
|
|||
|
cela permet de garder des bases de donn<6E>es coh<6F>rentes, plus facilement que si
|
|||
|
on devait mettre <20> jour leur contenu sur plusieurs centaines de machines <20> la
|
|||
|
fois.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
On dit plut<75>t aujourd'hui NIS ou Network Information System, Yellow Pages
|
|||
|
<EFBFBD>tant une marque d<>pos<6F>e de British Telecom.</p>
|
|||
|
|
|||
|
<p>
|
|||
|
La commande <tt>ypcat</tt> permet de visualiser une base de donn<6E>es: citons en
|
|||
|
particulier: <tt>ypcat passwd</tt>, <tt>ypcat group</tt>, <tt>ypcat
|
|||
|
hosts</tt>.</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Ces bases de donn<6E>es sont les versions centralis<69>es des fichiers
|
|||
|
<tt>/etc/passwd</tt>, <tt>/etc/group</tt> et <tt>/etc/hosts</tt>, lesquels ne
|
|||
|
contiennent alors plus que quelques informations; par exemple, le fichier
|
|||
|
<tt>/etc/hosts</tt> contient tout de m<>me des adresses de machines, ne
|
|||
|
serait-ce que celle du serveur de pages jaunes....
|
|||
|
</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li><a name="yp2"> <strong>Combien de personnes de la promotion 1996 ont un
|
|||
|
login commen<65>ant par <20>l<EFBFBD><6C>? </strong> </a> <p>
|
|||
|
|
|||
|
Pour avoir une liste de tous les comptes, on tape </p>
|
|||
|
|
|||
|
<pre>ypcat passwd</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
On veut ensuite s<>lectionner les gens dont le r<>pertoire personnel contient
|
|||
|
<tt>/96/</tt>, et dont le login commence par <tt>l</tt>, et compter le nombre
|
|||
|
de lignes (option <tt>-c</tt> de <tt>grep</tt>). On tape donc<6E>: </p>
|
|||
|
|
|||
|
<pre>ypcat passwd |grep c '^l.*/96/'</pre>
|
|||
|
<p>
|
|||
|
et on obtient 19.
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
|
|||
|
<li><a name="yp3"> <strong>Est-ce que des gens des promotions de la d<>cennie
|
|||
|
1980 ont encore un compte sur clipper<65>? </strong> </a> <p>
|
|||
|
|
|||
|
On veut savoir si des chemins d'acc<63>s de r<>pertoires personnels sont de la
|
|||
|
forme </p>
|
|||
|
|
|||
|
<pre>/users/8[0-9]</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
On tape donc<6E>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>ypcat passwd | grep '/users/8[0-9]'</pre></li>
|
|||
|
|
|||
|
|
|||
|
<li><a name="yp4"> <strong>Combien y a-t-il de comptes d'<27>l<EFBFBD>ves, magist<73>riens,
|
|||
|
etc (appartenant <20> une promotion) sur clipper<65>? </strong> </a> <p>
|
|||
|
|
|||
|
On veut avoir une liste des gens dont le chemin d'acc<63>s du r<>pertoire
|
|||
|
personnel commence par <tt>/users/</tt> et un num<75>ro<72>: <tt>/users/9[0-9]</tt>
|
|||
|
(puisqu'on vient de voir qu'il n'y a pas de gens des promotions ant<6E>rieures).
|
|||
|
On utilise l'option <tt>-c</tt> (<em>count</em>) pour avoir le nombre de
|
|||
|
personnes<EFBFBD>: </p>
|
|||
|
|
|||
|
<pre>ypcat passwd | grep -c '/users/9[0-9]/'</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li><a name="yp5"> <strong>Classer les comptes de ces utilisateurs par num<75>ro
|
|||
|
d'UID</strong> </a> <p>
|
|||
|
|
|||
|
|
|||
|
Le num<75>ro d'ID (<em>user identification</em>) identifie les utilisateurs, les
|
|||
|
num<EFBFBD>ros les plus bas correspondant au syst<73>me (l'UID de root est 0). C'est le
|
|||
|
troisi<EFBFBD>me champ, les champs <20>tant s<>par<61>s par des deux-points.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
On va utiliser <tt>sort</tt> pour trier, selon un crit<69>re num<75>rique (option
|
|||
|
<tt>-n</tt>). Par d<>faut, avec <tt>sort</tt> les champs sont d<>limit<69>s par des
|
|||
|
blancs, il faut donc indiquer qu'ici ce sont des deux-points, avec l'option
|
|||
|
<tt>-t</tt>. Enfin, on trie en fonction du troisi<73>me champ (<tt>2</tt>,
|
|||
|
la num<75>rotation commen<65>ant <20> 0). </p>
|
|||
|
|
|||
|
<p>
|
|||
|
On suppose aussi que l'on veut pouvoir lire le r<>sultat du tri avec
|
|||
|
<tt>less</tt>. On tape donc<6E>: </p>
|
|||
|
|
|||
|
<pre>ypcat passwd | grep '/users/9[0-9]' | sort -n -t: +2 | less</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
<li> <strong> <a name="yp6">Affichez le login des personnes ayant
|
|||
|
<tt>zsh</tt> comme shell de login.
|
|||
|
</a> </strong>
|
|||
|
|
|||
|
On utilise <code>grep</code> pour ne garder que les lignes des pages
|
|||
|
jaunes correspondant aux personnes ayant <code>zsh</code> comme shell de
|
|||
|
login et on utilise <code>sed</code> pour n'afficher que le login<69>:
|
|||
|
<pre>
|
|||
|
<span class="prompt">bireme ~ $</span><3E>ypcat passwd | grep "zsh$" | sed -e "s/:.*//"
|
|||
|
</pre>
|
|||
|
<div class="ens">
|
|||
|
Comme vous pourrez le constater, sur <code>clipper</code>, tout le
|
|||
|
monde <20> <code>/bin/sh</code> comme shell de login. Le shell (en g<>n<EFBFBD>ral
|
|||
|
<code>zsh</code>) n'est lanc<6E> qu'<27> partir du script
|
|||
|
<code>.profile</code>. Il s'agit d'un choix de l'administrateur syst<73>me.
|
|||
|
</div>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
<li> <strong> <a name="yp7">Affichez le nom et le pr<70>nom des personnes
|
|||
|
ayant un compte sur <tt>clipper</tt>, et dont le nom de famille contient au
|
|||
|
moins 2 voyelles c<>te <20> c<>te. Compter ces personnes. </a>
|
|||
|
</strong>
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">bireme ~ $</span><3E>ypcat passwd | sed -e "s/:\/.*//
|
|||
|
s/.*://" | grep " .*[aeiou][aeiou].*"
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
</ol>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<h2><a name="divers">Divers</a></h2>
|
|||
|
|
|||
|
<ol>
|
|||
|
|
|||
|
<li> <strong> <a name="divers1">Comment conserver les informations concernant
|
|||
|
le disque dans un fichier<65>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
C'est la commande <tt>df</tt> qui donne des informations sur le disque et sur
|
|||
|
les partitions mont<6E>es. Pour rediriger la sortie d'une commande dans un
|
|||
|
fichier, on utilise l'op<6F>rateur de redirection <tt>></tt> suivi du nom du
|
|||
|
fichier. Dans notre cas, pour conserver les informations dans un fichier
|
|||
|
appel<EFBFBD> <tt>disque</tt>, on <20>crira<72>:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
df > disque
|
|||
|
</pre></li>
|
|||
|
|
|||
|
<li>
|
|||
|
|
|||
|
<strong> <a name="divers3">Comment conna<6E>tre la derni<6E>re date de connexion au
|
|||
|
syst<EFBFBD>me d'un utilisateur de login <tt>martin</tt><3E>? </a> </strong>
|
|||
|
|
|||
|
<p>
|
|||
|
C'est la commande <tt>finger</tt> qui donne des renseignements sur les
|
|||
|
utilisateurs. Si on tape
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
finger martin
|
|||
|
</pre>
|
|||
|
|
|||
|
<p class="continue">
|
|||
|
ou mieux (plus rapide),
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
finger -m martin
|
|||
|
</pre>
|
|||
|
|
|||
|
<p class="continue">
|
|||
|
les renseignements concernant l'utilisateur s'affichent. On y trouve la
|
|||
|
date de son dernier login sur la machine o<> vous <20>tes, ainsi que la date de la
|
|||
|
derni<EFBFBD>re fois o<> il a lu son courrier (mais ce <20> condition qu'il ait re<72>u du
|
|||
|
courrier depuis...).
|
|||
|
</p></li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<!-- <p>
|
|||
|
<li><strong> <a name="divers4"> Cr<43>ez chez vous un fichier contenant des mots
|
|||
|
(sur le mod<6F>le d'un carnet de vocabulaire), un par ligne, avec des
|
|||
|
r<EFBFBD>p<EFBFBD>titions. </a></strong> <br>
|
|||
|
|
|||
|
Utilisez la commande <tt>uniq</tt><3E>:
|
|||
|
|
|||
|
<ul>
|
|||
|
<li> Pour <20>liminer les lignes redondantes (dans notre exemple, la ligne
|
|||
|
<EFBFBD>Pomme<EFBFBD> en double exemplaire);
|
|||
|
|
|||
|
<li> Pour donner le nombre d'occurrences de chaque ligne;
|
|||
|
|
|||
|
<li> Pour ne faire appara<72>tre que le ou les mots redondants avec le nombre
|
|||
|
d'occurrences; ici, ce sera<72>: <br>
|
|||
|
|
|||
|
<tt> 2 Pomme </tt>
|
|||
|
|
|||
|
|
|||
|
</ul>
|
|||
|
!-->
|
|||
|
|
|||
|
|
|||
|
<li><strong> <a name="divers5"> Affichez le type des fichiers <tt>/etc/passwd</tt>,
|
|||
|
<tt>/usr/include/stdio.h</tt>, <tt>/bin/ls</tt> et de votre r<>pertoire de
|
|||
|
travail. </a></strong>
|
|||
|
|
|||
|
<p>
|
|||
|
C'est la commande <tt>file</tt> qui permet d'afficher le type des fichiers.
|
|||
|
Dans notre cas, il suffit d'<27>crire:
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
<span class="prompt">galion ~ $</span><3E>file /etc/passwd /usr/include/stdio.h /bin/ls .
|
|||
|
/etc/passwd: ASCII text
|
|||
|
/usr/include/stdio.h: C program text
|
|||
|
/bin/ls: ELF 32-bit MSB executable, SPARC, version 1, stripped
|
|||
|
.: directory
|
|||
|
<span class="prompt">galion ~ $</span>
|
|||
|
</pre>
|
|||
|
</li>
|
|||
|
|
|||
|
</ol>
|
|||
|
|
|||
|
|
|||
|
<div class="metainformation">
|
|||
|
Auteur<75>: Anonyme, Jo<4A>l Riou. Derni<6E>re modification le 2002-12-09.
|
|||
|
</div>
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|
|||
|
|