# Find

## Introduction

Les exemples de ce tuto sont tous à faire en *user* sauf spécification.

Cette commande permet de faire des recherches de fichier ou de dossier dans une hiérarchie de répertoires.

Par exemple, je voudrais chercher le log messages, mais je sais pas où se trouve ce fichier, faites :

```
find / -name 'messages'
```

<div class="level2" id="bkmrk-r%C3%A9sultat-de-la-comma"><dl class="file"><dt>résultat de la commande précédente</dt><dd>```
/var/log/messages
```

</dd></dl></div>Voilà la réponse :   
Il se trouve dans le répertoire `/var/log`.

##### Nota

Notez l'utilisation des apostrophes *afin d'éviter que l'interpréteur de commande n'étende le motif*.   
Elles sont inutiles dans ce cas-ci mais c'est une bonne pratique de toujours les utiliser afin d'éviter l'extension *motif*.

## Quelques options

<div class="level2" id="bkmrk-options-fonctions--a"><div class="table sectionedit4"><table class="inline"><thead><tr class="row0"><th class="col0 centeralign">Options</th><th class="col1 centeralign">Fonctions</th></tr></thead><tbody><tr class="row1"><td class="col0 leftalign">-atime n ou +n ou -n</td><td class="col1 leftalign">*trouve les fichiers auxquels on a accédé il y a strictement n jours, ou plus de n jours, ou moins de n jours*</td></tr><tr class="row2"><td class="col0 leftalign">-mtime n ou +n ou -n</td><td class="col1 leftalign">*trouve les fichiers modifiés il y a strictement n jours, ou plus de n jours, ou moins de n jours*</td></tr><tr class="row3"><td class="col0 leftalign">-maxdepth n</td><td class="col1 leftalign">*définit le niveau maximum de sous-répertoire à explorer*</td></tr><tr class="row4"><td class="col0 leftalign">-type l ou d ou f</td><td class="col1 leftalign">*indique le type de fichier à rechercher (l pour lien symbolique, d pour répertoire (directory), f pour fichier)*</td></tr><tr class="row5"><td class="col0 leftalign">-name</td><td class="col1 leftalign">*recherche par motif en respectant la casse*</td></tr><tr class="row6"><td class="col0 leftalign">-iname</td><td class="col1 leftalign">*recherche par motif sans respecter la casse*</td></tr></tbody></table>

</div></div>## Recherche simple par nom

Example simple : comment trouver un fichier portant le nom `note` ?

```
find / -name 'note'
```

Décomposition de la commande de l'exemple :

<div class="level2" id="bkmrk-%E2%80%9C%2F%E2%80%9D-indique-que-nous">1. <div class="li">“`/`” indique que nous voulons chercher notre fichier à partir de la racine.</div>
2. <div class="li">“`-name` ” est l'option qui indique ici que nous voulons spécifier le nom d'un fichier.</div>

</div>Après un long délai d'attente, la recherche se faisant dans toute l'arborescence de la partition, la réponse finit par venir :

<div class="level2" id="bkmrk-r%C3%A9sultat-de-la-comma-1"><dl class="file"><dt>résultat de la commande précédente</dt><dd>```
/home/martin/note
```

</dd></dl></div>Si l'on n'est pas sûr de la casse (Majuscule ou minuscule) on utilise l'option `-iname`.

<div class="level2" id="bkmrk-r%C3%A8gle-g%C3%A9n%C3%A9rale%2C-on-r"><div class="plugin_note noteclassic">Règle générale, on recherche rarement un fichier depuis la racine.</div></div>Prenons un autre exemple.

Pour chercher tous les fichiers commençant par *note* et définir à partir de quel répertoire on souhaite effectuer la recherche on utilise cette syntaxe :

```
find /home/martin -name 'note*'
```

## Recherche par nom simple &amp; multiple

Maintenant, regardons, encore une fois à l'aide d'un exemple, la syntaxe de la commande **find** si l'on recherche plutôt un ou plusieurs répertoires.

Je cherche à trouver les répertoires archives dans /media/homebis. Première chose à noter, il peut-être nécessaire de se mettre en root pour avoir accès à tous les répertoires.

```
find /media/homebis -type d -name 'archives'
```

Dans ce cas-ci, je demande donc à **find** de trouver les répertoires

<div class="level2" id="bkmrk-option-%3A--type-argum">1. <div class="li">option : -type</div>
2. <div class="li">argument : “d” (comme “directory”)</div>

</div>indiquant que l'on cherche un répertoire du nom de *archives* à partir du répertoire /media/homebis.

La réponse :

<div class="level2" id="bkmrk-r%C3%A9sultat-de-la-comma-2"><dl class="file"><dt>résultat de la commande précédente</dt><dd>```
  /media/homebis/martin/textes/mes_archives/Baseball/archives
  /media/homebis/martin/archives
  /media/homebis/Documents_gr/Mots_croises/archives
  /media/homebis/Documents_gr/archives
  /media/homebis/Documents_gr/mes_fichiers/archives
```

</dd></dl></div>Autre exemple un peu plus complexe cette fois.   
Je désire faire une recherche de tous les fichiers audio de type .mp3 et .ogg

Il existe plus d'une façon d'y arriver.   
Voyons comment on peut s'y prendre.

### Première façon :

```
find /home/martin/  \( -name '*.mp3' -o -name '*.ogg' \)
```

<div class="level3" id="bkmrk-on-peut-noter-l%27util"><div class="plugin_note noteclassic">On peut noter l'utilisation du -o qui correspond à l'opérateur ou (“or” en anglais)</div></div>Cela me donnera toute une liste de fichiers /home/martin/…

### Deuxième façon :

Une autre manière d'écrire la commande ci-dessus est la suivante :

```
find -type f -name "*.mp3" -o -name "*.ogg"
```

Si je tape cette commande en étant dans mon répertoire /home/martin, le résultat sera une liste de fichiers ./….   
Il est intéressant de savoir que l'on peut étendre la recherche aux fichiers mp3 et mp4 en remplaçant le 3 par un ?<sup>[2)](https://debian-facile.org/doc:systeme:find#fn__2)</sup>. La commande deviendrait donc :

```
find -type f -name "*.mp?" -o -name "*.ogg"
```

## Rechercher pour supprimer

Une fonction intéressante de *find* est de supprimer en lot les fichiers trouvés.

Il n'est point rare de télécharger ou d'installer de nombreux fichiers qui ne nous servent plus, mais devant le travail pénible de devoir supprimer tous ces fichiers, on repousse au lendemain cette charge. Heureusement grâce à la fonction -delete de find, c'est un pur bonheur.

### Paramètre -delete

Exemple, si dans votre home ou autre dossier vous avez beaucoup de fichier .tar.gz qui ne vous servent plus à rien. Il suffit de lancer la commande suivante :

```
find -iname "*.tar.gz" -delete
```

<div class="level3" id="bkmrk-attention%2C-la-foncti"><div class="plugin_note noteimportant">**Attention, la fonction -delete ne vous demande pas de confirmation**</div></div>#### Supprimer avec demande de confirmation

Pour une demande de confirmation avant suppression de chaque fichier “.tar.gz” trouvés :

```
find -iname "*.tar.gz" -ok rm {} \;
```

Merci à MicP pour cette trouvaille :)

## Filtrer en fonction des droits

Une option très pratique est `-perm` qui permet de sélectionner des fichiers en fonctions de leurs droits.   
*Les droits peuvent être donné en forme octale, par exemple 0755 ou littérale, u=rwx,g=rw,o=rw.*

Voici par exemple comment obtenir la liste de tout les fichiers dans le repertoire `/bin` qui ont le `bit setuid valant 1` :

```
find /bin -perm /5000 -user root
```

<div class="level2" id="bkmrk-r%C3%A9sultat-de-la-comma-3"><dl class="file"><dt>résultat de la commande précédente</dt><dd>```
/bin/su
/bin/mount
/bin/umount
/bin/ping
/bin/ping6
```

</dd></dl></div>Cette option est intéressante pour la sécurité. Les fichiers listés dans la commande précédente sont tous exécuté avec les droits `root`.

<div class="level2" id="bkmrk-trois-notations-avec"><div class="plugin_note notetip">**Trois notations avec `perm`, sans préfixe, précédé du signe – ou précédé du signe /**  
- <div class="li">*sans préfixe* :</div>

</div></div>le mode du fichier doit être exactement celui passé à l’option -perm.  
Par exemple, si on cherche les fichiers ayant le mode u=rwx (0700), tous les fichiers que l’on trouvera auront exactement le mode u=rwx (0700).

<div class="level2" id="bkmrk-avec-le-signe-%E2%80%93-%3A"><div class="plugin_note notetip">- <div class="li">*avec le signe –* :</div>

</div></div>le mode du fichier doit être au moins égal à celui passé à l’option -perm  
-u=r (-0400) → u=r ou u=rw ou u=rx ou u=rwx ou u=r,g=x …

<div class="level2" id="bkmrk-avec-le-signe-%2F-%3A"><div class="plugin_note notetip">- <div class="li">*avec le signe /* :</div>

</div></div>un des modes (user, group ou other) doit être au moins égal à ceux passés à l’option -perm  
/u=w,g=w,o=w → u=w ou g=w ou o=w ou u=w,g=w,o=w ou u=rw,g=rwx …

## Recherche par motif

Pour rechercher un motif, il faut utiliser la même option, et utiliser les REGEXP.

Voici par exemple la recherche de tous les fichiers terminant par `.java` dans le dossier courant:

```
find . -name '*.java'
```

<div class="level2" id="bkmrk-r%C3%A9sultat-de-la-comma-4"><dl class="file"><dt>résultat de la commande précédente</dt><dd>```
./java/jdk1.5.0_06/demo/applets/Animator/Animator.java
./java/jdk1.5.0_06/demo/applets/ArcTest/ArcTest.java
./java/jdk1.5.0_06/demo/applets/BarChart/BarChart.java
./java/jdk1.5.0_06/demo/applets/Blink/Blink.java
./java/jdk1.5.0_06/demo/applets/CardTest/CardTest.java
...
```

</dd></dl></div>## Rechercher les fichiers n'appartenant pas à l'utilisateur

Il peut parfois être utile de rechercher les fichiers n'appartenant pas à l'utilisateur, en vue de corriger un problème rencontré avec une application (par exemple, un fichier peut appartenir à root au lieu d'appartenir à l'utilisateur ; ce dernier risque de ne pas avoir de droits dessus, ce que peut alors provoquer une erreur dans une application cherchant à modifier le dit fichier).

Pour ce faire, il suffit d'exécuter là commande suivante, où « utilisateur » est à remplacer par votre nom d'utilisateur :

```
find /home/utilisateur ! -user utilisateur
```

ou bien, en utilisant des variables :

```
find $HOME ! -user $USER
```

Pour avoir davantage d'informations sur les fichiers ainsi trouvés, vous pouvez ajouter l'option `ls` :

```
find $HOME ! -user $USER -ls
```

## -exec - Exécuter une commande

La commande **find** permet d'effectuer toute sorte d'action avec les fichiers trouvés.

Une action très utile est “`-exec`” qui permet d'exécuter une commande sur les fichiers sélectionnés.   
La syntaxe de `exec` est particulière car il faut pouvoir fournir le nom du fichier trouvé.

À la suite de la commande find habituelle, la syntaxe est :

```
 find /chemin/du/fichier/ <option> <caractéristique fichier> -exec commande {} \;
```

<div class="level2" id="bkmrk-la-paire-d%27accolade-">1. <div class="li">La paire d'accolade est automatiquement remplacée par le nom du fichier,</div>
2. <div class="li">et le point-virgule final permet de marquer la fin de la commande.</div>

</div>Au cas où plusieurs fichiers sont traités *dans un même répertoire*, pour éviter une relance de la commande après chaque fichier trouvé, remplacer le `;` (point-virgule) final par le signe positif : `+`.

Par exemple ainsi :

```
find /home/mon_user/test/ -type f -exec echo {} \+
```

<div class="level2" id="bkmrk-si-vous-utilisez-cet"><div class="plugin_note notewarning">Si vous utilisez cette option, veillez bien à ce que votre variable d’environnement **$PATH** ne contienne pas une référence au répertoire courant « . », sinon un pirate pourrait lancer toutes les commandes qu’il souhaite en mettant un fichier au nom adéquat dans les répertoires où vous allez lancer un -execdir.   
De la même manière, évitez les références vides ou les noms de répertoires exprimés en relatif dans **$PATH**.</div><div class="plugin_note noteimportant">Cette commande est difficile à utiliser sur certains shell car ceux-ci donnent une signification particulière des caractères comme l'accolade ou le point-virgule.</div></div>Avec **Bash**, la *paire d'accolades sans espace* (`{}`) ne doit pas être protégée, au contraire du *point-virgule* qui doit être échappé à l'aide d'un backslash: `\;`.

Voici par exemple comment on peut compter le nombre de lignes de chaque fichier de code Python de ce site:

```
   find developpement/django/certif -name '*.py' -exec wc -l {} \;
```

<div class="level2" id="bkmrk-r%C3%A9sultat-de-la-comma-5"><dl class="file"><dt>résultat de la commande précédente</dt><dd>```
       1 developpement/django/certif/__init__.py
       0 developpement/django/certif/acronym/__init__.py
      48 developpement/django/certif/acronym/models.py
      82 developpement/django/certif/acronym/tools.py
      13 developpement/django/certif/acronym/urls.py
      42 developpement/django/certif/acronym/views.py
      .../...
```

</dd></dl>1. <div class="li">Ici la commande **find** est utilisée avec l'option `-name` pour ne sélectionner que les fichiers se terminant par “`.py`” (extension de Python).</div>
2. <div class="li">La commande “`wc`” (qui compte le nombre de ligne avec -l) est invoquée à l'aide “`-exec`” sur chacun de ces fichiers.</div>

</div>Il existe d'autres variantes de l'exécution de commande comme l'option `-execdir` qui exécute la commande à partir du répertoire du fichier.

Comme d'habitude vous avez aussi le :

```
man find
```

*Entièrement disponible à votre curiosité !* ![;-)](https://debian-facile.org/lib/images/smileys/icon_wink.gif)