tuteurs.ens.fr/unix/exercices/solutions/find-sol.tml
2009-09-27 15:43:57 +02:00

239 lines
6.7 KiB
XML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
"tuteurs://DTD/tml.dtd">
<html>
<head>
<title>find</title>
</head>
<body>
<h1>Corrigés des exercices sur <code>find</code></h1>
<p>Ces exercices sont des questions de cours : les solutions se trouvent
toutes dans les pages de man des commandes en question. On suppose donc
connues les commandes de <code>less</code>, qui servent à se déplacer dans les
pages de man... et la commande servant à chercher un mot. Testez les
commandes sur des fichiers et répertoires d'essai pour vous faire la main et
comprendre ce qui se passe.
</p>
<h2>Les options de <code>find</code></h2>
<ol>
<li><a name="find1"> <strong>Comment chercher tous les fichiers dont les noms
commençent par un «a» majuscule ou une minuscule, suivi d'éventuellement
quelques lettres ou chiffres, et se terminent par un chiffre entre 3 et
6 ?</strong> </a> <p>
C'est l'option <code>-name</code> qui permet de spécifier le nom du ou des
fichiers recherchés. On peut indiquer le nom d'un fichier complet
(<code>bofichier.tex</code>), ou utiliser des expressions régulières (celles du
shell, pas celles de <code>grep</code>...) :</p>
<ul>
<li> L'étoile (<code>*</code>) désigne «un ou plusieurs caractères»;</li>
<li> Le point d'interrogation remplace un (et un seul) caractère
quelconque;</li>
<li> Les crochets permettent de désigner une série de caractères au
choix.</li>
</ul>
<p>
Dans notre cas, le premier caractère est un «a» ou un «A» (<code>[aA]</code>),
suivi de quelque chose (<code>*</code>) et terminé par un chiffre entre 3 et 6
(<code>[3456]</code> ou <code>[3-6]</code>). On écrit donc :
</p>
<pre>
find . -name '[aA]*[3-6]' -print
</pre>
</li>
<li><a name="find2"> <strong>Comment fait-on pour indiquer que le fichier
recherché a été modifié il y a plus de 30 jours ? Il y a 30 jours ?
Il y a moins de 30 jours?</strong> </a>
<p>
C'est l'option <code>-mtime</code> qui permet de donner une indication en
jours. La syntaxe varie selon ce que l'on souhaite :
</p>
<ul>
<li> <code>-mtime 30</code> : le fichier a été modifié il y a 30
jours;</li>
<li> <code>-mtime +30</code> : le fichier a été modifié il y a 30
jours ou plus;</li>
<li> <code>-mtime -30</code> : le fichier a été modifié il y a 30
jours ou moins.</li>
</ul></li>
<li><a name="find3"> <strong>Comment faire pour dire que le fichier a été
modifié plus récemment qu'un autre fichier donné ? </strong> </a><p>
On utilise l'option <code>-newer</code> («plus récent»). Par exemple, on
cherche un fichier <code>.tex</code> modifié plus récemment que
<code>bofichier.tex</code> :
</p>
<pre>
find . -newer bofichier.tex -name '*.tex'
</pre>
<p>
On peut raffiner la demande, en combinant cette option avec l'option
<code>-mtime</code> : cherchons les fichiers modifiés plus récemment que
<code>bofichier.tex</code>, mais il y a plus de 5 jours : </p>
<pre>
find . -newer bofichier.tex -mtime +5 -name '*.tex'
</pre></li>
<li><a name="find4"> <strong>Comment fait-on pour spécifier que le fichier
recherché est un répertoire ? </strong> </a><p>
On utilise l'option <code>-type</code> pour spécifier le genre de fichier
recherché : les principaux sont <code>f</code> (<em>file</em>) pour un
fichier normal, et <code>d</code> (<em>directory</em>) pour un répertoire.
On tape donc :
</p>
<pre>
find . -type d
</pre>
</li>
<li><a name="find5"> <strong>Comment indiquer que le fichier recherché à une
taille supérieure à une taille donnée ? </strong> </a> <p>
On utilise l'option <code>-size</code>, suivie d'un nombre et d'une lettre
indiquant l'unité de mesure (<code>c</code> : octets,
<code>k</code> : kilo-octets). Comme pour <code>-mtime</code>, on
utilise <code>+</code>, <code>-</code> ou <code>[rien]</code> pour indiquer
que la taille est, respectivement, supérieure, inférieure ou égale à la valeur
donnée.</p>
<p>
Par exemple, on recherche un fichier modifié il y a moins de 12 jours et dont
la taille soit supérieure à 30 K : </p>
<pre>
find . -type f -size +30k -mtime -12 -print
</pre></li>
</ol>
<h2>Exécuter des commandes sur les fichiers trouvés</h2>
<p><a name="find6"> <strong>Utiliser <code>find</code> pour effacer tous vos
fichiers de sauvegarde (terminés par un tilde) qui ont plus d'un mois.
</strong> </a></p> <p>
La ligne utilisée pour trouver ces fichiers et la suivante :
</p>
<pre>
find . -mtime +30 -name '*~'
</pre>
<p>
Il y a deux façons de faire exécuter des commandes sur les fichiers trouvés
par <code>find</code> : utiliser l'option «<code>-exec</code>
<em>commande</em>», ou utiliser un pipe avec <code>xargs</code>.
</p>
<ol>
<li> <strong><code>-exec</code> <em>commande</em></strong> exécute la commande
sur le fichier courant. La commande est terminée par le marqueur
<code>;</code>, qu'il faut protéger du shell avec un backslash. Le fichier
courant est désigné par la chaîne <code>{}</code>.
<p>
Pour effacer tous les fichiers de sauvegarde vieux de plus d'un mois, on tape
donc : </p>
<pre>
find . -mtime +30 -name '*~' -print -exec rm \;
</pre>
<p>
On peut faire exécuter la commande de façon interactive en remplaçant
<code>-exec</code> par <code>-ok</code> : </p>
<pre>
find . -mtime +30 -name '*~' -print -ok rm \;
</pre>
<p>
Le programme demande, pour chaque fichier trouvé, si on veut bien exécuter la
commande; la réponse doit être «<code>y</code>» ou «<code>Y</code>».
</p></li>
<li> La solution avec <code>-exec</code> est en fait très lourde, car elle
crée un nouveau processus pour chaque fichier; il vaut mieux
<strong>rediriger le résultat de <code>find</code> avec un pipe et
<code>xargs</code></strong>. Dans notre cas, on tapera donc :
<pre>
find . mtime +30 -name '*~' | xargs -p rm
</pre>
<p>
L'option <code>-p</code> de <code>xargs</code> rend cette commande
interactive. Il faut répondre «<code>y</code>» ou «<code>Y</code>» pour
confirmer.
</p></li>
</ol>
<p>
Quelle différence y a-t-il entre un simple pipe et
«<code>| xargs</code>» ? Pour la comprendre, voici un
exercice : cherchez tous les fichiers contenus dans
<code>/usr/local/lib/texmf/tex</code> et cherchez dedans le mot «supertab». Il
y a deux solutions :
</p>
<ol>
<li> Vous tapez
<pre>
find /usr/local/lib/texmf/tex -type f | grep supertab
</pre>
<p>
Vous obtenez une liste de fichiers contenant «supertab» dans leur nom.
</p>
</li>
<li> Vous tapez
<pre>
find /usr/local/lib/texmf/tex -type f | xargs grep supertab
</pre>
<p>
<code>grep</code> cherche dans chaque fichier passé en argument la chaîne de
caractères «supertab», ce qui est très différent...</p></li>
</ol>
<div class="metainformation">
Auteur : Émilia Robin, Joël Riou. Dernière modification le
<date value="$Date: 2007-07-17 10:03:37 $"/>.
</div>
</body>
</html>