« Recherche de fichiers » : différence entre les versions

De La Mouche VII
Aller à la navigationAller à la recherche
Aucun résumé des modifications
 
m (Révocation des modifications de 208.109.190.98 (discussion) vers la dernière version de Xiloynaha)
 
(11 versions intermédiaires par 4 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
find . -regex '.*~' -exec rm '{}' ';'
[[Catégorie:Informatique]]
 
== locate ==
 
La commande '''locate''' est un peu la solution de facilité pour chercher des fichiers. J'exagère un peu : '''locate''' est en effet plus facile à utiliser que '''find''', mais elle a d'autres avantages.
 
=== Principe de fonctionnement ===
 
'''locate''' utilise une base de données de fichiers créée préalablement, et cherche dans cette base un nom de fichier donné.
 
'''''Avantage''''' : la recherche est très rapide.
 
'''''Inconvénients''''' : comme il faut parcourir toute l'arborescence du système, la mise à jour de la base de donnée est longue et on ne la fait donc pas souvent. Cela implique qu'une recherche a des chances de donner des résultats faux (un fichier qui n'existe plus sur le disque mais encore présent dans la base de données), ou de ne pas donner tous les résultats (les fichiers créés depuis la dernière mise à jour ne seront pas trouvés).
 
=== Utilisation ===
 
Comme vous l'avez compris l'utilisation de '''locate''' est très simple.
 
Pour mettre à jour la base de données, tapez simplement (en root) :
# updatedb
Il est possible d'exécuter cette commande en simple utilisateur, mais la base construite ne comportera pas les fichiers situés dans des répertoires auxquels l'utilisateur n'a pas accès (et des messages d'erreur apparaitront pour chacun de ces répertoires).
 
Ne faites pas attention aux messages d'erreur « ''Aucun fichier ou répertoire de ce type'' ».
 
Pour rechercher un fichier, tapez :
$ locate fichier
Tous les noms de fichiers contenant ''fichier'' seront affichées.
 
== find ==
 
La commande '''find''' recherche récursivement toutes les occurrences d'un fichier (quel que soit son type) à partir d'un répertoire. En français, cela veut dire qu'on lui donne un répertoire et un nom à chercher, et qu'il va regarder dans le répertoire lui-même ainsi que tous les répertoires fils (sous-répertoires) si le fichier recherché existe. Si oui il l'affiche avec son chemin relatif. Il y a aussi d'autres possibilités, comme d'exécuter une commande sur le fichier au lieu de simplement afficher son nom.
 
=== Recherche simple par motif : ''-name'' et ''-iname'' ===
 
Pour chercher toutes les occurrences du fichier ''fichier'' dans le répertoire ''répertoire'', la syntaxe est la suivante :
$ find répertoire -name fichier
Il faut donc avant tout donner le répertoire dans lequel chercher, puis l'option '''-name''' sert à spécifier le fichier à rechercher. Comme d'habitude, si l'un des deux contient des espaces il faut le protéger avec des guillemets simples (') ou doubles ("). Si l'on veut rechercher sans tenir compte de la casse, on utilise l'option '''-iname''' :
$ find répertoire -iname fichier
À la place du nom, on peut aussi spécifier un motif ; pour rechercher tous les fichiers d'en-tête C dans le répertoire ''répertoire'' on peut écrire :
$ find répertoire -name '*.h'
 
Par exemple, si j'ai une arborescence de fichiers :
répertoire1/fichier1
répertoire1/répertoire2/fichier1
répertoire1/répertoire2/Fichier1
répertoire1/répertoire2/fichier2
répertoire1/répertoire3/fichier1
répertoire1/répertoire3/FICHIER1
répertoire1/répertoire4/fichier3
et que je veux chercher le fichier ''fichier1'', je vais taper :
$ find répertoire1 -name fichier1
Il va alors m'afficher :
répertoire1/répertoire2/fichier1
répertoire1/répertoire3/fichier1
répertoire1/fichier1
 
Si je veux effectuer la même recherche, mais sans tenir compte de la casse, je tape :
$ find répertoire1 -iname fichier1
Et j'obtiens :
répertoire1/répertoire2/fichier1
répertoire1/répertoire2/Fichier1
répertoire1/répertoire3/fichier1
répertoire1/répertoire3/FICHIER1
répertoire1/fichier1
 
Si je veux chercher tous les fichiers dont le nom finit par le chiffre 3, je tape :
$ find répertoire1 -name '*3'
Et j'obtiens :
répertoire1/répertoire3
répertoire1/répertoire4/fichier3
 
À noter que si aucun nom de fichier n'est spécifié, '''find''' affichera simplement la liste de tous les fichiers de l'arborescence :
$ find répertoire1/
répertoire1/
répertoire1/répertoire2
répertoire1/répertoire2/fichier1
répertoire1/répertoire2/Fichier1
répertoire1/répertoire2/fichier2
répertoire1/répertoire3
répertoire1/répertoire3/fichier1
répertoire1/répertoire3/FICHIER1
répertoire1/répertoire4
répertoire1/répertoire4/fichier3
répertoire1/fichier1
 
=== Recherche simple avec expression rationnelle : ''-regex'' et ''-iregex'' ===
 
Les options '''-name''' et '''-iname''' suffisent dans la plupart des cas, mais peuvent être limites si le motif à rechercher est très complexe.
 
Mais que l'on se rassure, il est également possible de rechercher tous les fichiers correspondant à un certain motif : il suffit de remplacer l'option '''-name''' par '''-regex''' (pour ''regular expression'') '''-iname''' par '''-iregex''' et le nom du fichier par une… expression rationnelle, tout à fait !
 
'''''Avertissement :''' dans le traitement de l'expression rationnelle, ce qui est pris en compte est l'ensemble de la ligne de sortie potentielle, et pas le nom du fichier. Par exemple si je cherche à partir du répertoire courant (<tt>find . -regex mon_expression</tt>), chaque ligne commencera par « <tt>./</tt> », et il faudra en tenir compte dans l'écriture de l'expression.''
 
Cela nous donne donc :
$ find répertoire -regex 'expression'
La protection de l'expression par des guillemets simples est indispensable (pour éviter au shell d'interpréter les * par exemple).
 
Mais… Que mettre à la place de l'expression ? Eh bien je ne vais pas expliquer les expressions régulières ici, mais juste donner quelques exemples.
 
Rechercher les fichiers commençant par ''début'' :
$ find répertoire -regex 'début.*'
 
Rechercher les fichiers finissant par ''fin'' :
$ find répertoire -regex '.*fin'
 
Rechercher les fichiers contenant ''mot'' :
$ find répertoire -regex '.*mot.*'
 
Bon allez, petite explication quand même : dans l'expression régulière, le point ('.') remplace n'importe quel caractère, et l'astérisque ('*') signifie que le caractère précédent est répété un nombre quelconque de fois.
 
La chaîne '''<nowiki>'.*'</nowiki>''' veut donc dire « autant de caractères quelconques que l'on veut », autrement dit n'importe quelle chaîne de caractères, et '''<nowiki>'.*fin'</nowiki>''' se traduit par « n'importe quelle chaîne suivie de "fin" », ou encore « une chaîne de caractères se terminant par "fin" ».
 
=== Traitement des fichiers trouvés ===
 
Comme je l'ai dit plus haut '''find''' a l'avantage de pouvoir effectuer des traitements sur les fichiers trouvés.
 
==== Sans confirmation ====
 
L'option idoine est '''-exec'''.
 
La syntaxe est assez peu intuitive. Derrière '''-exec''', on met la commande à exécuter suivie de ses arguments. La chaîne '''{}''' remplace le nom du fichier courrant. Pour signifier la fin des options de la commande à exécuter, on met un point-virgule. Pour éviter que le shell n'interprète les accolades et le point-virgule, on les protège.
$ find répertoire -name fichier -exec commande -arg1 -arg2 '{}' ';'
exécute la commande '''commande''' sur chaque fichier trouvé, avec les arguments '''-arg1''' et '''-arg2''' de '''commande'''.
 
Par exemple pour rechercher et supprimer tous les fichiers finissant par le caractère '~' à partir du répertoire courant :
$ find . -regex '.*~' -exec rm -v '{}' ';'
On utilise ici l'option '''-v''' de '''rm''' pour avoir la liste des fichiers supprimés.
 
==== Avec confirmation ====
 
Si on veut que '''find''' demande confirmation avant d'exécuter la commande, on peut utiliser '''-ok''' à la place de '''-exec''' :
$ find répertoire -name fichier -ok commande -arg1 -arg2 '{}' ';'
Pour chaque fichier trouvé, find affiche la commande qu'il va exécuter et attendra confirmation. Si on tape '''y''' (ou '''o''' dans un environnement français), la commande est exécutée ; dans les autres cas '''find''' poursuit sa recherche.
 
Exemple :
$ find répertoire1/ -name fichier1 -ok rm -v '{}' ';'
< rm  répertoire1/répertoire2/fichier1 > ? y
détruit `répertoire1/répertoire2/fichier1'
< rm ... répertoire1/répertoire3/fichier1 > ? 
< rm ... répertoire1/fichier1 > ?
Ici l'utilisateur a confirmé la suppression du premier fichier en tapant '''y''', mais a simplement appuyé sur '''<ENTRÉE>''' pour les deux autres, ce qui est interprété comme un refus.
 
Remarque : dans ce cas précis, on peut utiliser '''-exec''' et l'option '''-i''' de '''rm''' plutôt que '''-ok'''.
 
== Conclusion ==
 
Je me suis limité à l'utilisation de base de ces programmes (celle que j'en fais, en fait).
 
Pour un peu plus d'informations concernant les possibilités présentées, et pour en découvrir beaucoup d'autres, n'hésitez pas :
$ man updatedb
$ man locate
$ man find
 
Sous Debian, '''locate''' et '''find''' se trouvaient traditionnellement dans le paquet '''findutils''', normalement installé par défaut. Dans les versions récentes, '''locate''' est dans un paquet séparé, et '''mlocate''', une version améliorée, est proposé par défaut.

Dernière version du 7 mars 2010 à 19:52


locate

La commande locate est un peu la solution de facilité pour chercher des fichiers. J'exagère un peu : locate est en effet plus facile à utiliser que find, mais elle a d'autres avantages.

Principe de fonctionnement

locate utilise une base de données de fichiers créée préalablement, et cherche dans cette base un nom de fichier donné.

Avantage : la recherche est très rapide.

Inconvénients : comme il faut parcourir toute l'arborescence du système, la mise à jour de la base de donnée est longue et on ne la fait donc pas souvent. Cela implique qu'une recherche a des chances de donner des résultats faux (un fichier qui n'existe plus sur le disque mais encore présent dans la base de données), ou de ne pas donner tous les résultats (les fichiers créés depuis la dernière mise à jour ne seront pas trouvés).

Utilisation

Comme vous l'avez compris l'utilisation de locate est très simple.

Pour mettre à jour la base de données, tapez simplement (en root) :

# updatedb

Il est possible d'exécuter cette commande en simple utilisateur, mais la base construite ne comportera pas les fichiers situés dans des répertoires auxquels l'utilisateur n'a pas accès (et des messages d'erreur apparaitront pour chacun de ces répertoires).

Ne faites pas attention aux messages d'erreur « Aucun fichier ou répertoire de ce type ».

Pour rechercher un fichier, tapez :

$ locate fichier

Tous les noms de fichiers contenant fichier seront affichées.

find

La commande find recherche récursivement toutes les occurrences d'un fichier (quel que soit son type) à partir d'un répertoire. En français, cela veut dire qu'on lui donne un répertoire et un nom à chercher, et qu'il va regarder dans le répertoire lui-même ainsi que tous les répertoires fils (sous-répertoires) si le fichier recherché existe. Si oui il l'affiche avec son chemin relatif. Il y a aussi d'autres possibilités, comme d'exécuter une commande sur le fichier au lieu de simplement afficher son nom.

Recherche simple par motif : -name et -iname

Pour chercher toutes les occurrences du fichier fichier dans le répertoire répertoire, la syntaxe est la suivante :

$ find répertoire -name fichier

Il faut donc avant tout donner le répertoire dans lequel chercher, puis l'option -name sert à spécifier le fichier à rechercher. Comme d'habitude, si l'un des deux contient des espaces il faut le protéger avec des guillemets simples (') ou doubles ("). Si l'on veut rechercher sans tenir compte de la casse, on utilise l'option -iname :

$ find répertoire -iname fichier

À la place du nom, on peut aussi spécifier un motif ; pour rechercher tous les fichiers d'en-tête C dans le répertoire répertoire on peut écrire :

$ find répertoire -name '*.h'

Par exemple, si j'ai une arborescence de fichiers :

répertoire1/fichier1
répertoire1/répertoire2/fichier1
répertoire1/répertoire2/Fichier1
répertoire1/répertoire2/fichier2
répertoire1/répertoire3/fichier1
répertoire1/répertoire3/FICHIER1
répertoire1/répertoire4/fichier3

et que je veux chercher le fichier fichier1, je vais taper :

$ find répertoire1 -name fichier1

Il va alors m'afficher :

répertoire1/répertoire2/fichier1
répertoire1/répertoire3/fichier1
répertoire1/fichier1

Si je veux effectuer la même recherche, mais sans tenir compte de la casse, je tape :

$ find répertoire1 -iname fichier1

Et j'obtiens :

répertoire1/répertoire2/fichier1
répertoire1/répertoire2/Fichier1
répertoire1/répertoire3/fichier1
répertoire1/répertoire3/FICHIER1
répertoire1/fichier1

Si je veux chercher tous les fichiers dont le nom finit par le chiffre 3, je tape :

$ find répertoire1 -name '*3'

Et j'obtiens :

répertoire1/répertoire3
répertoire1/répertoire4/fichier3

À noter que si aucun nom de fichier n'est spécifié, find affichera simplement la liste de tous les fichiers de l'arborescence :

$ find répertoire1/
répertoire1/
répertoire1/répertoire2
répertoire1/répertoire2/fichier1
répertoire1/répertoire2/Fichier1
répertoire1/répertoire2/fichier2
répertoire1/répertoire3
répertoire1/répertoire3/fichier1
répertoire1/répertoire3/FICHIER1
répertoire1/répertoire4
répertoire1/répertoire4/fichier3
répertoire1/fichier1

Recherche simple avec expression rationnelle : -regex et -iregex

Les options -name et -iname suffisent dans la plupart des cas, mais peuvent être limites si le motif à rechercher est très complexe.

Mais que l'on se rassure, il est également possible de rechercher tous les fichiers correspondant à un certain motif : il suffit de remplacer l'option -name par -regex (pour regular expression) -iname par -iregex et le nom du fichier par une… expression rationnelle, tout à fait !

Avertissement : dans le traitement de l'expression rationnelle, ce qui est pris en compte est l'ensemble de la ligne de sortie potentielle, et pas le nom du fichier. Par exemple si je cherche à partir du répertoire courant (find . -regex mon_expression), chaque ligne commencera par « ./ », et il faudra en tenir compte dans l'écriture de l'expression.

Cela nous donne donc :

$ find répertoire -regex 'expression'

La protection de l'expression par des guillemets simples est indispensable (pour éviter au shell d'interpréter les * par exemple).

Mais… Que mettre à la place de l'expression ? Eh bien je ne vais pas expliquer les expressions régulières ici, mais juste donner quelques exemples.

Rechercher les fichiers commençant par début :

$ find répertoire -regex 'début.*'

Rechercher les fichiers finissant par fin :

$ find répertoire -regex '.*fin'

Rechercher les fichiers contenant mot :

$ find répertoire -regex '.*mot.*'

Bon allez, petite explication quand même : dans l'expression régulière, le point ('.') remplace n'importe quel caractère, et l'astérisque ('*') signifie que le caractère précédent est répété un nombre quelconque de fois.

La chaîne '.*' veut donc dire « autant de caractères quelconques que l'on veut », autrement dit n'importe quelle chaîne de caractères, et '.*fin' se traduit par « n'importe quelle chaîne suivie de "fin" », ou encore « une chaîne de caractères se terminant par "fin" ».

Traitement des fichiers trouvés

Comme je l'ai dit plus haut find a l'avantage de pouvoir effectuer des traitements sur les fichiers trouvés.

Sans confirmation

L'option idoine est -exec.

La syntaxe est assez peu intuitive. Derrière -exec, on met la commande à exécuter suivie de ses arguments. La chaîne {} remplace le nom du fichier courrant. Pour signifier la fin des options de la commande à exécuter, on met un point-virgule. Pour éviter que le shell n'interprète les accolades et le point-virgule, on les protège.

$ find répertoire -name fichier -exec commande -arg1 -arg2 '{}' ';'

exécute la commande commande sur chaque fichier trouvé, avec les arguments -arg1 et -arg2 de commande.

Par exemple pour rechercher et supprimer tous les fichiers finissant par le caractère '~' à partir du répertoire courant :

$ find . -regex '.*~' -exec rm -v '{}' ';'

On utilise ici l'option -v de rm pour avoir la liste des fichiers supprimés.

Avec confirmation

Si on veut que find demande confirmation avant d'exécuter la commande, on peut utiliser -ok à la place de -exec :

$ find répertoire -name fichier -ok commande -arg1 -arg2 '{}' ';'

Pour chaque fichier trouvé, find affiche la commande qu'il va exécuter et attendra confirmation. Si on tape y (ou o dans un environnement français), la commande est exécutée ; dans les autres cas find poursuit sa recherche.

Exemple :

$ find répertoire1/ -name fichier1 -ok rm -v '{}' ';'
< rm  répertoire1/répertoire2/fichier1 > ? y
détruit `répertoire1/répertoire2/fichier1'
< rm ... répertoire1/répertoire3/fichier1 > ?  
< rm ... répertoire1/fichier1 > ?

Ici l'utilisateur a confirmé la suppression du premier fichier en tapant y, mais a simplement appuyé sur <ENTRÉE> pour les deux autres, ce qui est interprété comme un refus.

Remarque : dans ce cas précis, on peut utiliser -exec et l'option -i de rm plutôt que -ok.

Conclusion

Je me suis limité à l'utilisation de base de ces programmes (celle que j'en fais, en fait).

Pour un peu plus d'informations concernant les possibilités présentées, et pour en découvrir beaucoup d'autres, n'hésitez pas :

$ man updatedb
$ man locate
$ man find

Sous Debian, locate et find se trouvaient traditionnellement dans le paquet findutils, normalement installé par défaut. Dans les versions récentes, locate est dans un paquet séparé, et mlocate, une version améliorée, est proposé par défaut.