tuteurs.ens.fr/unix/exercices/solutions/find-sol.tml
meles 26abda08cc Bap: Grosses modifications en série sur tout le site :
1) insertion de balises <date value="$Date$"/>
2) remplacement des espaces insécables par des &nbsp;
3) insertion d'espaces insécables autour des guillemets français
2007-07-13 08:40:16 +00:00

239 lines
6.8 KiB
XML

<?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&nbsp;: 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&nbsp;?</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>...)&nbsp;:</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&nbsp;:
</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&nbsp;? Il y a 30 jours&nbsp;?
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&nbsp;:
</p>
<ul>
<li> <code>-mtime 30</code>&nbsp;: le fichier a été modifié il y a 30
jours;</li>
<li> <code>-mtime +30</code>&nbsp;: le fichier a été modifié il y a 30
jours ou plus;</li>
<li> <code>-mtime -30</code>&nbsp;: 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é&nbsp;? </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>&nbsp;:
</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>&nbsp;: cherchons les fichiers modifiés plus récemment que
<code>bofichier.tex</code>, mais il y a plus de 5 jours&nbsp;: </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&nbsp;? </strong> </a><p>
On utilise l'option <code>-type</code> pour spécifier le genre de fichier
recherché&nbsp;: 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&nbsp;:
</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&nbsp;? </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>&nbsp;: octets,
<code>k</code>&nbsp;: 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&nbsp;: </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&nbsp;:
</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>&nbsp;: 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&nbsp;: </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>&nbsp;: </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&nbsp;:
<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>|&nbsp;xargs</code>»&nbsp;? Pour la comprendre, voici un
exercice&nbsp;: cherchez tous les fichiers contenus dans
<code>/usr/local/lib/texmf/tex</code> et cherchez dedans le mot «supertab». Il
y a deux solutions&nbsp;:
</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&nbsp;: Émilia Robin, Joël Riou. Dernière modification le
<date value="$Date: 2007-07-13 08:41:42 $"/>.
</div>
</body>
</html>