La commande find ou la puissance de la recherche

dimanche 30 mars 2008
par  zarer (Christophe Gallaire)
popularité : 100%

La commande find fait partie des commandes avancées les plus efficaces dans l’administration d’un système — elle nécessite les privilèges de l’administrateur pour effectuer une recherche sur un ou plusieurs systèmes de fichiers. Si vous ne savez pas endosser ces privilèges, reportez-vous à l’article Linux connexion ! Si la recherche est limitée au seul répertoire de l’utilisateur, nul besoin de ces privilèges.

La commande find est un outil extrêmement puissant, doté d’une cinquantaine d’options, autorisant des recherches définies selon des critères très fins : sur fichiers, répertoires, liens symboliques... à partir du nom (en tenant compte de la casse ou non), selon le propriétaire, la taille, la date, etc, dans un unique système de fichiers ou plus ! Il faut ajouter que ses options se définissent selon deux catégories : sélection et exécution. On mesure alors toute l’étendue de la puissance de cette commande.

La syntaxe de la commande find n’est malheureusement pas des plus courantes. Quelques essais sauront vous convaincre, si ce n’est déjà le cas, de l’adopter au plus vite.

Pour l’anedocte, c’est grâce à cette commande redoutable que j’ai retrouvé, sur mon disque externe, un fichier égaré qui me faisait cruellement défaut depuis plusieurs années :

find /media/IOMEGA_HDD -print0 | xargs --null grep chaplin

Comme le montre la ligne ci-dessus, la commande find s’associe à merveille avec la commande xargs. Par les ressources conjuguées des dites commandes, il s’agissait donc de rechercher dans l’arborescence de mon disque tous les fichiers contenant le mot "chaplin"... find a su retrouver la trace de mon vieux fichier inséré dans un fichier de sauvegarde datant de 2004 ! Chapeau l’artiste !

La preuve par l’exemple

Au-delà de l’ergonomie indéniable des outils graphiques, ce qui doit faire la différence est avant tout l’efficacité et la rapidité du résultat. Alors, mettons à l’épreuve les commandes locate, find et l’outil graphique Beagle Search.

Pour cet exemple de recherche, compliquons quelque peu la tâche de nos compétiteurs. La machine de test comprend plusieurs disques durs donc plusieurs partitions, plusieurs systèmes de fichiers, plusieurs OS (Libres only... cela va de soi !). Certaines partitions ne sont dédiées qu’au stockage pur et dur et c’est bien entendu sur ces partitions que la recherche devra faire ses preuves.

locate et Beagle

Avec une syntaxe élémentaire, le résultat de la commande locate ne correspond absolument pas à celui escompté. Pour obtenir satisfaction, il m’aurait fallu créer mon propre index et très certainement préciser davantage les critères de recherche (chemin, type de fichier, etc.). Mais restons simples.

locate "artemis*" /usr/share/app-install/icons/_usr_share_pixmaps_artemis.xpm
/usr/share/app-install/desktop/artemis.desktop

En mode graphique, Beagle ne fait pas bien mieux : un seul résultat pour un fichier de plein texte qui n’a absolument rien à voir avec l’objet recherché !

La commande find... seul et unique vainqueur !

Voici la commande find en action dans une syntaxe basique, histoire de ne pas trop désavantager ses adversaires :

sudo find / -name "artemis*" -print
[sudo] password for zarer :
/media/disk/documents_pro/2007_2008/lectures/artemis_fowl.odt
/usr/share/app-install/desktop/artemis.desktop

Bingo ! au premier coup d’essai ! Waoooooo ! Pour ma part, il ne m’en faut pas plus pour me convaincre : l’objet recherché est trouvé rapidement, au travers de différents systèmes de fichiers, sans entrer nombre d’options obscures. Remarquable.

En ajoutant une seule option, le propriétaire, le résultat aurait été immanquable :

sudo find / -name "artemis*" -user zarer -print
[sudo] password for zarer :
/media/disk/documents_pro/2007_2008/lectures/artemis_fowl.odt

gnome-search-tool : find, locate et grep conjuguées !

L’application Recherche de fichiers est la seule, à ma connaissance (disponible immédiatement à l’utilisateur fraîchement débarqué sous Linux avec le bureau Gnome), à pouvoir rivaliser avec find. La raison :

La Recherche de fichiers exploite les commandes UNIX find, grep et locate. Par défaut, lors d’une recherche élémentaire, la Recherche de fichiers utilise d’abord la commande locate, et dans un deuxième temps la commande find, plus lente, mais plus efficace.

Ben voui voui voui ! Y a du find là-d’ssous !

Présentation de la commande find

Vous l’aurez compris, cette commande est à ranger parmi les "grands classiques" pour l’administration : find est un outil de base, que cela soit en mode ligne de commandes ou dans les scripts shells.

La commande find recherche des objets (fichiers, répertoires, liens, etc.) dans l’arborescence qui débute au répertoire donné en argument, selon des critères définis, et exécute une action sur cet objet. Le critère de sélection le plus utilisé est le nom de l’objet (fichier, répertoire, ...) et l’action la plus fréquente l’affichage du chemin d’accès à l’objet recherché.

Sa syntaxe générale est la suivante :

find /répertoire_de_recherche -option1 -option2 ...

Voici quelques exemples simples de recherche dans tout ou partie du (ou des) système(s) de fichiers :

Exemple 1

Dans ce premier exemple, la commande doit chercher un fichier spécifique nommé mon_premier_fichier à partir du répertoire racine (voir le schéma de l’arborescence UNIX) et afficher le résultat à l’écran :

find / -type f -name mon_premier_fichier -print

Exemple 2

Les utilisateurs même les mieux ordonnés savent combien il est parfois difficile de se souvenir du nom exact que l’on a donné à tel ou tel fichier. La commande find autorise elle aussi l’utilisation des caractères jokers ou de substitution :

find / -type f -name *fichier -print

Dans un nom de fichier (ou de répertoire) les caractères jokers ou caractères de substitution jouent un rôle particulier pour l’interpréteur de commandes : ils remplacent un nombre variable de caractères selon le caractère joker employé.

L’astérique (*)

L’étoile ou (ou astérisque) remplace un nombre quelconque de caractères (y compris aucun). Elle peut être placée n’importe où dans le nom. On se sert souvent de ce caractère pour lister des fichiers sur la base d’une partie du nom.

Le point d’interrogation (?)

Le point d’interrogation ne remplace qu’un caractère et un seul. Il peut être placé n’importe où dans le nom du fichier (répertoire), comme dans les exemples ci-dessous pour la recherche d’un fichier nommé fichier1 ou fichier10 :

find / -type f -name fichier? -print
find / -type f -name fichier?? -print

Les crochets ([])

Les crochets sont identiques au point d’interrogation seulement la substitution ne s’effectue qu’avec l’un des caractères présentés entre crochets : [abc], [0-9], [!abc] pour un caractère différent de a, b et c, [!0-5], ...

Exemple 3

Dans ce troisième exemple, la commande doit lister tous les répertoires contenus dans mon répertoire personnel et afficher le résultat à l’écran :

find /home/zarer -type d -print

Quelques options utiles pour recherche avancée

Les options de la commande find se partage en deux catégories : sélection et exécution.

Options pour critères de sélection

Les critères de sélection sont très nombreux et s’appliquent sur le type (fichier, répertoire, ...) et les attributs (propriétaire, groupe, permissions, date de création ou de modification, taille, ...) des objets de la recherche. Contentons-nous d’en présenter quelques-uns (voir la page du manuel de la commande find) :

-name : effectue une recherche en fonction du nom (sans les répertoires du chemin d’accès). Si le nom défini contient des caractères jokers, il est préférable de l’encadrer de guillemets ou d’apostrophes.

-iname : identique à -name mais sans différencier les majuscules et les minuscules.

find / -iname "*fichier*" -print

-type : Cette option précise le type de l’objet recherché. Elle doit être suivie par une lettre qui le définit. Par exemple : d = répertoire, f = fichier régulier ou "normal", l = lien symbolique.

find / -type f -iname "artemis*" -print

L’exemple ci-dessous recherche depuis le répertoire racine tous les fichiers avec l’extension .odt et les affiche :

find / -type f -iname "*.odt" -print

-user : Fichier appartenant à l’utilisateur indiqué. Extrêmement pratique pour l’administrateur d’un ou plusieurs postes multi-utilisateurs.

-group : Fichier appartenant au groupe indiqué.

-mount : La recherche est limitée à un unique système de fichiers ; elle ne doit pas s’effectuer sur les répertoires situés sur d’autres systèmes de fichiers. Il s’agit d’une alternative à l’option -xdev, assurant la compatibilité avec d’anciennes versions de find.

Attention ! Un certain ordre s’impose ! Les options sont dites "positionnelles". Leur contrôle est effectué dans l’ordre de la ligne de commande. À défaut, vous risquez d’obtenir un message du genre :

find : AVERTISSEMENT : vous avez spécifié l’option -mount après un argument qui n’est pas une option -type mais les options sont positionnelles (-mount affecte les tests spécifiés avant aussi bien qu’après)

On conçoit aisément que l’option limitant la recherche au seul système de fichiers soit placée avant le nom du fichier (ou répertoire) recherché et, qu’une fois localisé, il faille ensuite afficher le chemin de l’objet :

find / -mount -type f -iname "*.pdf" -user zarer -print

Options pour critères d’exécution

Une fois spécifiés les critères de recherche, il est possible de demander à la commande find différentes opérations sur les objets trouvés. La principale opération est tout bonnement d’afficher le résultat de la recherche (le chemin d’accès à l’objet). Encore une fois, les options sont là aussi nombreuses. Reportez-vous à la page du manuel de la commande find pour en connaître le détail.

Les critères de sélection s’appliquent sur le type (fichier, répertoire, ...) et les attributs des objets de la recherche. Contentons-nous d’en présenter quelques-uns :

-print : Affiche le résultat de la recherche sous la forme d’une liste de chemins d’accès aux objets (fichiers, répertoires...) répondant aux critères de sélection. C’est l’utilisation la plus courante de la commande find.

-exec commande ; : Exécute la commande. Tous les arguments de find sont considérés comme des arguments pour la ligne de commande, jusqu’à ce qu’on rencontre un " ;". La chaîne "{}" est remplacée par le nom du fichier en cours de traitement, et ceci dans toutes ses occurrences. Ces deux chaînes peuvent avoir besoin d’être protégées du développement de la ligne de commande par le shell, en utilisant le caractère d’échappement ("\") ou une protection par des apostrophes. La commande est exécutée depuis le répertoire de départ.

Le résultat de la recherche peut ainsi servir à d’autres commandes (destruction, sauvegarde, affiche page par page, etc.), comme dans l’exemple de syntaxe de la ligne ci-dessous qui enchaîne la commande rm qui détruira sans demande de confirmation le résultat de la recherche :

find /home -iname mon_fichier_essai -exec rm -f {} \;

Si vous avez des craintes ou des doutes lors de l’exécution d’une commande à risque il est dans ce cas préférable d’utiliser l’option suivante :

-ok commande ; : Cette option est identique à -exec mais interroge d’abord l’utilisateur. Si la réponse ne commence pas par "y" ou "Y", la commande ne sera pas exécutée :

find /home -iname mon_fichier_essai -ok rm -f {} \;
< rm ... /home/zarer/Desktop/mon_fichier_essai > ?

Recherche avec plusieurs critères

Quand plusieurs options sont utilisées simultanément, tous les critères sont vérifiés. Entre chacune des options, la commande find use d’un opérateur logique implicite : "Et".

Il est possible de modifier cette règle, en appliquant des opérateurs explicites. Ces opérateurs sont rarement employés mais il peut être intéressant de les connaître pour, par exemple, regrouper plusieurs noms. La syntaxe de la ligne ci-dessous permet de rechercher un objet dont le nom contient deux expressions :

find / \( -iname *image* -a -iname *chaplin* \) -print

Les opérateurs logiques sont présentés dans l’ordre de priorité décroissante :

\( expression \) : Les parenthèses forcent la priorité. Comme en algèbre, ce qui se trouve entre les parenthèses doit être évalué avant toute autre opération.

! expression ou -not expression : Vrai si l’expression est fausse. Consiste tout simplement à prendre l’expression comme fausse. On peut par exemple rechercher un fichier qui n’appartient pas à tel ou tel utilisateur.

expression1 expression2 : ET (implicite). L’expression2 ne sera pas évaluée si l’expression1 est fausse.

expression1 -a expression2 ou expression1 -and expression2 : Comme expression1 expression2. Le -a est donc optionnel.

expression1 -o expression2 ou expression1 -or expression2 : OU. L’expression2 n’est pas évaluée si l’expression1 est vraie.

expression1 , expression2 : Liste. Les expressions seront toujours évaluées toutes les deux. La valeur de l’expression1 est ignorée ; la valeur de la liste est celle de l’expression2.

Bonne recherche !


Commentaires  forum ferme

Logo de tuxce
vendredi 4 avril 2008 à 14h00 - par  tuxce

salut,

Tout bonnement pour rester dans une syntaxe des plus simples. Nul doute, comme je le précise dans l’article, qu’en multipliant les options et en indexant les fichiers, locate aurait été plus efficace.

non mais, je m’étais trompé, je pensais que locate n’acceptait qu’un seul motif :)

Logo de vivegrepaussi
lundi 31 mars 2008 à 01h44 - par  vivegrepaussi

Juste une remarque concernant la commande « find /media/IOMEGA_HDD -print0 | xargs —null grep chaplin » où dans le cas présent c’est plutôt grep qui se tape tout le boulot de recherche :-)
Ici, find est utilisé dans sa fonction la plus basique qui est de lister toute une arborescence pour donner du grain à moudre à ce bon vieux grep !

Logo de zarer (Christophe Gallaire)
dimanche 30 mars 2008 à 23h57 - par  zarer (Christophe Gallaire)

Bonsoir tuxce,

le motif passé aux commandes (artemis*) devrait être échapé pour éviter une complétion par le shell

Exact. D’autant que je le dis quelque part dans l’article et que je l’avais fait sur certaines occurrences.

find ne nécessite pas les privilèges root à moins que tu ne veuilles chercher des fichiers non accessibles à l’utilisateur.

Oui oui... je vais faire cette précision. Mais je pars du principe que tout fichier peut être recherché par l’admin, possiblement sur plusieurs systèmes de fichiers (j’ai plusieurs disques, normal). Beaucoup d’utilisateurs sont aussi l’admin de leur machine. Dans le cas où l’on veut rechercher dans son espace perso, tu as raison.

pour locate, il suffit que les périphériques soient branchés lors d’un scan et ne soient pas exclus depuis /etc/updatedb.conf

Oui oui... après mise-à-jour.

beagle comme tracker sont configurés par défaut pour n’indexer que le répertoire perso (plutot logique)

Oui très juste mais Beagle est tout de même peu efficace de prime abord. P’têt qu’en le paramétrant il est meilleur... soit. Je n’ai jamais creusé la question. je le trouve trop lent.

il ne devrait pas y avoir d’espace entre \ et ;

C’est une erreur générée manifestement par le SPIP. Je n’y avais pas fait attention.

et une petite question, pourquoi avoir lancé "locate" avec 2 paramètres ?

Tout bonnement pour rester dans une syntaxe des plus simples. Nul doute, comme je le précise dans l’article, qu’en multipliant les options et en indexant les fichiers, locate aurait été plus efficace.

Merci pour ta lecture attentive.

Logo de tuxce
dimanche 30 mars 2008 à 23h03 - par  tuxce

quelques petites remarques :
- le motif passé aux commandes (artemis*) devrait être échapé pour éviter une complétion par le shell
- pour locate, il suffit que les périphériques soient branchés lors d’un scan et ne soient pas exclus depuis /etc/updatedb.conf
- beagle comme tracker sont configurés par défaut pour n’indexer que le répertoire perso (plutot logique)
- find ne nécessite pas les privilèges root à moins que tu ne veuilles chercher des fichiers non accessibles à l’utilisateur.
- il ne devrait pas y avoir d’espace entre \ et ;

et une petite question, pourquoi avoir lancé "locate" avec 2 paramètres ?

Logo de traaf
dimanche 30 mars 2008 à 16h03 - par  traaf

chapeau bas, un article vraiment très complet, j’ai appris plein de choses.

Logo de KissCoolMan
dimanche 30 mars 2008 à 14h10 - par  KissCoolMan

Merci pour la découverte du "-ok" , c’est génial !

Logo de b52 (Claude)
dimanche 30 mars 2008 à 13h20 - par  b52 (Claude)

Salut @Zarer ;)

IL est vrai qu’Unix tire toute sa puissance de la ligne de commande via des programmes qui effectuent des choses simples qui lorsqu’ils sont ’tubés’ sont redoutables d’efficacités !

Merci à toi pour cette re découverte ;)