| Linux-Mandrake: Manuel de référence | ||
|---|---|---|
| Page précédente | Chapitre 12. Les utilitaires en ligne de commande | Page suivante |
find est un utilitaire Unix de longue date. Son but est de parcourir récursivement un ou plusieurs répertoires et d'y trouver des fichiers correspondant à un certain ensemble de critères. Bien qu'il soit très utile, sa syntaxe est vraiment complexe, et l'utiliser requiert une certaine habitude. La syntaxe générale est :
find [options] [répertoires] [critère] [action] |
Si vous ne spécifiez aucun répertoire, find recherchera dans le répertoire courant. Si vous ne spécifiez pas de critère, c'est équivalent à « vrai », et donc tous les fichiers seront trouvés. Les options, critères et actions sont si nombreux que nous n'en mentionnerons que quelques-uns ici. Commençons par les options :
-xdev : Ne pas étendre la recherche aux répertoires se trouvant sur d'autres systèmes de fichiers.
-mindepth <n> : Descendre d'au moins <n> niveaux en-dessous du répertoire de recherche avant de chercher des fichiers.
-maxdepth <n> : Rechercher les fichiers se trouvant au plus n niveaux en-dessous du répertoire de recherche.
-follow : Suivre les liens symboliques s'il pointent vers des répertoires. Par défaut, find ne les suivra pas.
-daystart : Quand il est fait usage de tests relatifs à la date et l'heure, (voir ci-dessous), prendre le début de la journée courante comme repère au lieu de la marque par défaut (24 heures avant l'heure courante).
Un critère peut être un ou plusieurs tests atomiques; quelques tests utiles sont :
-type <type> : Rechercher un type de fichiers donné; <type> peut être : f (fichier régulier), d (répertoire), l (lien symbolique), s (socket), b (fichier en mode bloc), c (fichier en mode caractère) or p (tube nommé).
-name <motif> : Trouver les fichiers dont les noms correspondent au <motif> donné. Avec cette option, <motif> est traité comme un motif d'englobement du shell (voyez le chapitre Motifs d'englobement du shell, expressions rationnelles).
-iname <motif> : Comme -name, mais ne tient pas compte de la casse.
-atime <n>, -amin <n> : Trouver les fichiers dont la dernière date d'accès remonte à <n> jours (-atime) ou <n> minutes (-amin). Vous pouvez aussi spécifier +<n> ou -<n>, auquel cas la recherche sera effectuée sur les fichiers accédés au plus ou au moins <n> jours/minutes auparavant.
-anewer <fichier> : Trouver les fichiers dont la dernière date d'accès est plus récente que celle du fichier <fichier>
-ctime <n>, -cmin <n>, -cnewer <fichier> Même chose que pour -atime, -amin et -anewer, mais s'applique à la dernière date de changement du contenu des fichiers.
-regex <motif> : Comme pour -name, mais motif est traité comme une expression rationnelle.
-iregex <motif> : Comme -regex, mais sans tenir compte de la casse.
Beaucoup d'autres tests existent, référez-vous à la page de manuel pour plus de détails. Pour combiner ces tests, vous pouvez utiliser :
<c1> -a <c2> : Vrai si <c1> and <c2> sont vrais tous les deux; -a est implicite, donc vous pouvez utiliser <c1> <c2> <c3> ... si vous voulez que tous les tests <c1>, <c2>, ... soient vérifiés.
<c1> -o <c2> : Vrai si l'un de <c1> ou <c2> est vrai, ou les deux. Notez que -o a une priorité moins grande que -a, donc si vous voulez, par exemple, que les fichiers correspondant aux critères <c1> ou <c2> et qu'ils vérifient obligatoirement le critère <c3>, vous devrez utiliser des parenthèses et écrire ( <c1> -o <c2> ) -a <c3>. Vous devez échapper (désactiver) les parenthèses, sans quoi le shell les interprétera!
-not <c1> : Inverse le test <c1>, donc -not <c1> est vrai si <c1> est faux.
Enfin, vous pouvez spécifier une action pour chaque fichier trouvé. Les plus fréquentes sont :
-print : Ne fait qu'écrire le nom de chaque fichier sur la sortie standard. C'est l'action par défaut si vous n'en spécifiez aucune.
-ls : Affiche l'équivalent d'un ls -ilds sur chaque fichier trouvé sur la sortie standard.
-exec <command> : Exécute la commande <command> sur chaque fichier trouvé. La ligne de commande <command> doit se terminer par un ;, que vous devez désactiver de telle sorte que le shell ne l'interprète pas; la position du fichier est repérée par {}. Regardez les exemples d'utilisation pour comprendre.
-ok <command> : Même chose que -exec mais demander confirmation pour chaque commande.
Toujours là? Alors, maintenant entraînons-nous un peu, car c'est toujours la meilleure façon de comprendre le monstre. Supposons que vous vouliez trouver tous les répertoires dans /usr/share. Vous taperez alors :
find /usr/share -type d
Supposons que vous ayez un serveur HTTP, tous vos fichiers HTML sont dans /home/httpd/html, qui est aussi votre répertoire courant. Vous voulez trouver tous les fichiers qui n'ont pas été modifiés depuis un mois. Comme vous avez des pages de différents auteurs, certains fichiers ont une extension html et d'autres l'extension htm. Vous voulez lier ces fichiers dans le répertoire /home/httpd/obsolete. Vous taperez alors :
find \( -name "*.htm" -o -name "*.html" \) -a -ctime -30 \
-exec ln {} /home/httpd/obsolete \; |
![]() | Cet exemple requiert que /home/httpd et /home/httpd/obsolete soient sur le même système de fichiers! |
D'accord, cette exemple est un peu compliqué et requiert quelques explications. Le critère est :
\( -name "*.htm" -o -name "*.html" \) -a -ctime -30
qui fait ce que l'on veut : il recherche tous les fichiers dont le nom se termine soit par .htm, soit par .html (\( -name "*.htm" -o -name "*.html" \)), et (-a) qui n'ont pas été modifiés dans les 30 derniers jours, ce qui représente en gros un mois (-ctime -30). Notez les parenthèses : elles sont nécessaires ici, parce que -a a une priorité plus grande. S'il n'y en avait pas, tous les fichiers se terminant par .htm auraient été trouvés, plus tous les fichiers se terminant par .html et qui n'ont pas été modifiés depuis un mois, ce qui n'est pas ce que nous voulons. Notez également que les parenthèses sont désactivées par rapport au shell : si nous avions mis ( .. ) à la place de \( .. \), le shell les aurait interprétées et essayé d'exécuter -name "*.htm" -o -name "*.html" dans un sous-shell... Une autre solution aurait été de mettre les parenthèses entre doubles apostrophes ou simples apostrophes, mais une anti-barre oblique (backslash) est préférable ici dans la mesure où nous ne devons isoler qu'un seul caractère.
Et enfin, il y a la commande à exécuter pour chacun des fichiers :
-exec ln {} /home/httpd/obsolete \;
Ici aussi, vous devez désactiver le ; par rapport au shell, car autrement le shell l'interprétera comme un séparateur de commandes. Si vous ne le faites pas, find se plaindra qu'il manque un argument à -exec.
Un dernier exemple : vous avez un gros répertoire nommé /shared/images, avec toutes sortes d'images dedans. Régulièrement, vous utilisez la commande touch pour mettre à jour les dates d'un fichier nommé stamp dans ce répertoire, de façon à avoir une référence dans le temps. Vous voulez trouver tous les fichiers JPEG dans ce répertoire qui sont plus récents que le fichier stamp, et comme vous avez des images de diverses sources, ces fichiers ont des extensions jpg, jpeg, JPG ou JPEG. Vous voulez aussi éviter de rechercher dans le répertoire old. Vous voulez vous faire envoyer la liste de ces fichiers par courrier électronique, et votre nom d'utilisateur est jean :
find /shared/images -cnewer \
/shared/images/stamp \
-a -iregex ".*\.jpe?g" \
-a -not -regex ".*/old/.*" \
| mail jean -s "Nouvelles images" |
Et voilà! Bien sûr, cette commande n'est pas très utile si vous devez la taper à chaque fois, et vous voudriez l'exécuter régulièrement. Vous pouvez le faire :
| Page précédente | Début | Page suivante |
| Les utilitaires en ligne de commande | Remonter | crontab : exécuter des commandes périodiques |