tuteurs.ens.fr/unix/exercices/solutions/find-sol.tml

240 lines
6.7 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>find</title>
</head>
<body>
<h1>Corrig<69>s des exercices sur <code>find</code></h1>
<p>Ces exercices sont des questions de cours<72>: 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 <20> se d<>placer dans les
pages de man... et la commande servant <20> 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<EFBFBD>ent par un <20>a<EFBFBD> majuscule ou une minuscule, suivi d'<27>ventuellement
quelques lettres ou chiffres, et se terminent par un chiffre entre 3 et
6<EFBFBD>?</strong> </a> <p>
C'est l'option <code>-name</code> qui permet de sp<73>cifier le nom du ou des
fichiers recherch<63>s. On peut indiquer le nom d'un fichier complet
(<code>bofichier.tex</code>), ou utiliser des expressions r<>guli<6C>res (celles du
shell, pas celles de <code>grep</code>...)<29>:</p>
<ul>
<li> L'<27>toile (<code>*</code>) d<>signe <20>un ou plusieurs caract<63>res<65>;</li>
<li> Le point d'interrogation remplace un (et un seul) caract<63>re
quelconque;</li>
<li> Les crochets permettent de d<>signer une s<>rie de caract<63>res au
choix.</li>
</ul>
<p>
Dans notre cas, le premier caract<63>re est un <20>a<EFBFBD> ou un <20>A<EFBFBD> (<code>[aA]</code>),
suivi de quelque chose (<code>*</code>) et termin<69> par un chiffre entre 3 et 6
(<code>[3456]</code> ou <code>[3-6]</code>). On <20>crit donc<6E>:
</p>
<pre>
find . -name '[aA]*[3-6]' -print
</pre>
</li>
<li><a name="find2"> <strong>Comment fait-on pour indiquer que le fichier
recherch<EFBFBD> a <20>t<EFBFBD> modifi<66> il y a plus de 30 jours<72>? Il y a 30 jours<72>?
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<74>:
</p>
<ul>
<li> <code>-mtime 30</code><3E>: le fichier a <20>t<EFBFBD> modifi<66> il y a 30
jours;</li>
<li> <code>-mtime +30</code><3E>: le fichier a <20>t<EFBFBD> modifi<66> il y a 30
jours ou plus;</li>
<li> <code>-mtime -30</code><3E>: le fichier a <20>t<EFBFBD> modifi<66> il y a 30
jours ou moins.</li>
</ul></li>
<li><a name="find3"> <strong>Comment faire pour dire que le fichier a <20>t<EFBFBD>
modifi<EFBFBD> plus r<>cemment qu'un autre fichier donn<6E><6E>? </strong> </a><p>
On utilise l'option <code>-newer</code> (<28>plus r<>cent<6E>). Par exemple, on
cherche un fichier <code>.tex</code> modifi<66> plus r<>cemment que
<code>bofichier.tex</code><3E>:
</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><3E>: cherchons les fichiers modifi<66>s plus r<>cemment que
<code>bofichier.tex</code>, mais il y a plus de 5 jours<72>: </p>
<pre>
find . -newer bofichier.tex -mtime +5 -name '*.tex'
</pre></li>
<li><a name="find4"> <strong>Comment fait-on pour sp<73>cifier que le fichier
recherch<EFBFBD> est un r<>pertoire<72>? </strong> </a><p>
On utilise l'option <code>-type</code> pour sp<73>cifier le genre de fichier
recherch<EFBFBD><EFBFBD>: 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<6E>:
</p>
<pre>
find . -type d
</pre>
</li>
<li><a name="find5"> <strong>Comment indiquer que le fichier recherch<63> <20> une
taille sup<75>rieure <20> une taille donn<6E>e<EFBFBD>? </strong> </a> <p>
On utilise l'option <code>-size</code>, suivie d'un nombre et d'une lettre
indiquant l'unit<69> de mesure (<code>c</code><3E>: octets,
<code>k</code><3E>: 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<75>rieure, inf<6E>rieure ou <20>gale <20> la valeur
donn<EFBFBD>e.</p>
<p>
Par exemple, on recherche un fichier modifi<66> il y a moins de 12 jours et dont
la taille soit sup<75>rieure <20> 30 K<>: </p>
<pre>
find . -type f -size +30k -mtime -12 -print
</pre></li>
</ol>
<h2>Ex<45>cuter des commandes sur les fichiers trouv<75>s</h2>
<p><a name="find6"> <strong>Utiliser <code>find</code> pour effacer tous vos
fichiers de sauvegarde (termin<69>s par un tilde) qui ont plus d'un mois.
</strong> </a></p> <p>
La ligne utilis<69>e pour trouver ces fichiers et la suivante<74>:
</p>
<pre>
find . -mtime +30 -name '*~'
</pre>
<p>
Il y a deux fa<66>ons de faire ex<65>cuter des commandes sur les fichiers trouv<75>s
par <code>find</code><3E>: utiliser l'option <20><code>-exec</code>
<em>commande</em><3E>, ou utiliser un pipe avec <code>xargs</code>.
</p>
<ol>
<li> <strong><code>-exec</code> <em>commande</em></strong> ex<65>cute la commande
sur le fichier courant. La commande est termin<69>e par le marqueur
<code>;</code>, qu'il faut prot<6F>ger du shell avec un backslash. Le fichier
courant est d<>sign<67> par la cha<68>ne <code>{}</code>.
<p>
Pour effacer tous les fichiers de sauvegarde vieux de plus d'un mois, on tape
donc<EFBFBD>: </p>
<pre>
find . -mtime +30 -name '*~' -print -exec rm \;
</pre>
<p>
On peut faire ex<65>cuter la commande de fa<66>on interactive en rempla<6C>ant
<code>-exec</code> par <code>-ok</code><3E>: </p>
<pre>
find . -mtime +30 -name '*~' -print -ok rm \;
</pre>
<p>
Le programme demande, pour chaque fichier trouv<75>, si on veut bien ex<65>cuter la
commande; la r<>ponse doit <20>tre <20><code>y</code><3E> ou <20><code>Y</code><3E>.
</p></li>
<li> La solution avec <code>-exec</code> est en fait tr<74>s lourde, car elle
cr<EFBFBD>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<6E>:
<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 <20><code>y</code><3E> ou <20><code>Y</code><3E> pour
confirmer.
</p></li>
</ol>
<p>
Quelle diff<66>rence y a-t-il entre un simple pipe et
<EFBFBD><code>|<7C>xargs</code><3E><>? Pour la comprendre, voici un
exercice<EFBFBD>: cherchez tous les fichiers contenus dans
<code>/usr/local/lib/texmf/tex</code> et cherchez dedans le mot <20>supertab<61>. Il
y a deux solutions<6E>:
</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 <20>supertab<61> 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<73> en argument la cha<68>ne de
caract<EFBFBD>res <20>supertab<61>, ce qui est tr<74>s diff<66>rent...</p></li>
</ol>
<div class="metainformation">
Auteur<75>: <20>milia Robin, Jo<4A>l Riou. Derni<6E>re modification le
<date value="$Date: 2007-07-17 10:03:37 $"/>.
</div>
</body>
</html>