# find

# Corrigés des exercices sur `find`

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 `less`, 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.

## Les options de `find`

1. 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 ?

   C'est l'option `-name` qui permet de spécifier le nom du ou des fichiers recherchés. On peut indiquer le nom d'un fichier complet (`bofichier.tex`), ou utiliser des expressions régulières (celles du shell, pas celles de `grep`...) :

   - L'étoile (`*`) désigne «un ou plusieurs caractères»;
   - Le point d'interrogation remplace un (et un seul) caractère quelconque;
   - Les crochets permettent de désigner une série de caractères au choix.

   Dans notre cas, le premier caractère est un «a» ou un «A» (`[aA]`), suivi de quelque chose (`*`) et terminé par un chiffre entre 3 et 6 (`[3456]` ou `[3-6]`). On écrit donc :

       find . -name '[aA]*[3-6]' -print

2. 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?

   C'est l'option `-mtime` qui permet de donner une indication en jours. La syntaxe varie selon ce que l'on souhaite :

   - `-mtime 30` : le fichier a été modifié il y a 30 jours;
   - `-mtime +30` : le fichier a été modifié il y a 30 jours ou plus;
   - `-mtime -30` : le fichier a été modifié il y a 30 jours ou moins.
3. Comment faire pour dire que le fichier a été modifié plus récemment qu'un autre fichier donné ?

   On utilise l'option `-newer` («plus récent»). Par exemple, on cherche un fichier `.tex` modifié plus récemment que `bofichier.tex` :

       find . -newer bofichier.tex -name '*.tex'

   On peut raffiner la demande, en combinant cette option avec l'option `-mtime` : cherchons les fichiers modifiés plus récemment que `bofichier.tex`, mais il y a plus de 5 jours :

       find . -newer bofichier.tex -mtime +5 -name '*.tex'

4. Comment fait-on pour spécifier que le fichier recherché est un répertoire ?

   On utilise l'option `-type` pour spécifier le genre de fichier recherché : les principaux sont `f` (file) pour un fichier normal, et `d` (directory) pour un répertoire. On tape donc :

       find . -type d

5. Comment indiquer que le fichier recherché à une taille supérieure à une taille donnée ?

   On utilise l'option `-size`, suivie d'un nombre et d'une lettre indiquant l'unité de mesure (`c` : octets, `k` : kilo-octets). Comme pour `-mtime`, on utilise `+`, `-` ou `[rien]` pour indiquer que la taille est, respectivement, supérieure, inférieure ou égale à la valeur donnée.

   Par exemple, on recherche un fichier modifié il y a moins de 12 jours et dont la taille soit supérieure à 30 K :

       find . -type f -size +30k -mtime -12 -print

## Exécuter des commandes sur les fichiers trouvés

Utiliser `find` pour effacer tous vos fichiers de sauvegarde (terminés par un tilde) qui ont plus d'un mois.

La ligne utilisée pour trouver ces fichiers et la suivante :

    find . -mtime +30 -name '*~'

Il y a deux façons de faire exécuter des commandes sur les fichiers trouvés par `find` : utiliser l'option «`-exec` commande», ou utiliser un pipe avec `xargs`.

1. `-exec` commande exécute la commande sur le fichier courant. La commande est terminée par le marqueur `;`, qu'il faut protéger du shell avec un backslash. Le fichier courant est désigné par la chaîne `{}`.

   Pour effacer tous les fichiers de sauvegarde vieux de plus d'un mois, on tape donc :

       find . -mtime +30 -name '*~' -print -exec rm  \;

   On peut faire exécuter la commande de façon interactive en remplaçant `-exec` par `-ok` :

       find . -mtime +30 -name '*~' -print  -ok  rm  \;

   Le programme demande, pour chaque fichier trouvé, si on veut bien exécuter la commande; la réponse doit être «`y`» ou «`Y`».

2. La solution avec `-exec` est en fait très lourde, car elle crée un nouveau processus pour chaque fichier; il vaut mieux rediriger le résultat de `find` avec un pipe et `xargs`. Dans notre cas, on tapera donc :

       find . mtime +30 -name '*~' | xargs -p rm

   L'option `-p` de `xargs` rend cette commande interactive. Il faut répondre «`y`» ou «`Y`» pour confirmer.

Quelle différence y a-t-il entre un simple pipe et «`| xargs`» ? Pour la comprendre, voici un exercice : cherchez tous les fichiers contenus dans `/usr/local/lib/texmf/tex` et cherchez dedans le mot «supertab». Il y a deux solutions :

1. Vous tapez

       find /usr/local/lib/texmf/tex -type f | grep supertab

   Vous obtenez une liste de fichiers contenant «supertab» dans leur nom.

2. Vous tapez

       find /usr/local/lib/texmf/tex -type f | xargs grep supertab

   `grep` cherche dans chaque fichier passé en argument la chaîne de caractères «supertab», ce qui est très différent...

Auteur : Émilia Robin, Joël Riou. Dernière modification le 2002-12-09.