Objectifs
- Trouver des fichiers et dossiers en utilisant des critères précis (nom, type, taille, date) avec
find. - Exécuter une commande sur chaque fichier trouvé en utilisant l’option
-execdefind. - Construire des commandes complexes en combinant la sortie de
findavecxargs. - Comprendre pourquoi la combinaison
find ... -print0 | xargs -0 ...est essentielle pour la robustesse.
Explications détaillées
Notions clés
find : Le chercheur de fichiers récursif
find est un outil extrêmement puissant pour rechercher des fichiers et des dossiers à partir d’un point de départ, de manière récursive. Sa force réside dans ses “prédicats”, qui sont des conditions de recherche.
Syntaxe de base : find [chemin_de_depart] [expression_de_test] [action]
Tests courants :
-name "motif": Cherche par nom. Le motif peut contenir des jokers (*,?). Doit être cité.-iname "motif": Comme-name, mais ignore la casse.-type f: Ne trouve que les fichiers.-type d: Ne trouve que les dossiers.-size +10M: Fichiers de plus de 10 mégaoctets. (-pour moins,kpour ko,Gpour Go).-mtime -7: Fichiers modifiés il y a moins de 7 jours. (+7pour plus de 7 jours).-empty: Fichiers ou dossiers vides.
Actions courantes :
-print: L’action par défaut. Affiche le chemin complet.-delete: Supprime les fichiers trouvés. À utiliser avec une extrême prudence.-exec commande {} \;: Exécutecommandepour chaque fichier trouvé.{}est remplacé par le chemin du fichier.\;est obligatoire pour marquer la fin de la commande.- C’est sûr, mais lent, car un processus est lancé pour chaque fichier.
-exec commande {} +: Regroupe les fichiers trouvés et exécute la commande une seule fois avec un maximum d’arguments. C’est beaucoup plus efficace.
xargs : Construire des commandes à partir d’un flux
xargs est un outil qui lit du texte depuis l’entrée standard et l’utilise pour construire et exécuter des lignes de commande. C’est le partenaire naturel de find.
find . -name "*.txt" | xargs rm
Le problème des noms de fichiers
Que se passe-t-il si un nom de fichier contient un espace, comme "mon rapport.txt" ?
La commande find . -name "*.txt" | xargs rm échouera, car xargs verra mon, rapport.txt comme deux arguments distincts.
La solution robuste : \0
Pour résoudre ce problème, on utilise un caractère spécial qui ne peut pas exister dans un nom de fichier : le caractère nul (\0).
find ... -print0:findutilise\0comme séparateur au lieu d’un saut de ligne.xargs -0 ...:xargslit son entrée en utilisant\0comme séparateur.
Cette combinaison est la seule manière 100% fiable de passer une liste de fichiers de find à xargs.
Syntaxe / Usages
# Trouver tous les fichiers .log dans le dossier courant et ses sous-dossiers
find . -type f -name "*.log"
# Trouver et supprimer tous les fichiers temporaires (.tmp) modifiés il y a plus de 30 jours
find /tmp -type f -name "*.tmp" -mtime +30 -delete
# Compter le nombre de lignes de tous les fichiers .c (lent mais sûr)
find . -name "*.c" -exec wc -l {} \;
# Même chose, mais beaucoup plus rapide
find . -name "*.c" -exec wc -l {} +
# Changer les permissions de tous les scripts .sh (méthode xargs robuste)
find . -type f -name "*.sh" -print0 | xargs -0 chmod +x
Exemples
# Créons un environnement de test
mkdir -p demo_find/dossier_avec_espace
touch demo_find/a.txt "demo_find/dossier_avec_espace/un fichier.log" demo_find/b.txt
cd demo_find
# 1. Problème classique
# 'ls' sera appelé avec "dossier_avec_espace/un", "fichier.log", etc.
find . -type f | xargs ls -l # -> Erreur ou comportement incorrect
# 2. Solution robuste
find . -type f -print0 | xargs -0 ls -l
# -> Affiche correctement les informations pour "un fichier.log"
# 3. Supprimer tous les fichiers .txt
# Dry run (test à blanc) en remplaçant 'rm' par 'echo'
find . -type f -name "*.txt" -print0 | xargs -0 echo rm
# Si la liste est correcte, on exécute la vraie commande
find . -type f -name "*.txt" -print0 | xargs -0 rm
Bonnes pratiques
- Adoptez
find ... -print0 | xargs -0 ...comme un réflexe. C’est la garantie que vos scripts ne casseront pas sur des noms de fichiers exotiques. - Avant d’exécuter une commande destructive (
rm,mv, …), faites toujours un “dry run” en remplaçant la commande parechopour vérifier ce qui sera exécuté. - Pour des recherches simples dans l’arborescence actuelle, le globbing étendu de Bash 4+ (
shopt -s globstar; ls **/*.txt) peut être une alternative plus simple.
Pièges courants
- Ne pas utiliser
-print0et-0. C’est la source de 99% des problèmes avecfind | xargs. - Oublier de citer le motif de
-name:find . -name *.txtsera interprété par le shell avantfindsi des fichiers .txt sont dans le dossier courant. Il fautfind . -name "*.txt". - Complexité des prédicats :
findpermet des logiques-and(implicite),-or,-not, qui peuvent devenir complexes à lire.
Exercices
-
Chasse aux gros fichiers :
- Écrivez une commande
findqui liste tous les fichiers de plus de 50 Mo dans votre dossier personnel (~).
- Écrivez une commande
-
Nettoyage de dossiers vides :
- Écrivez une commande
findpour trouver et supprimer tous les dossiers vides dans votre projet. - Faites un “dry run” avec
echoavant de lancer le-delete.
- Écrivez une commande
-
Recherche de texte récursive et robuste :
- Écrivez une seule ligne de commande qui cherche la chaîne de caractères “TODO” (insensible à la casse) dans tous les fichiers
.pyde votre projet. - La commande doit être robuste aux noms de fichiers contenant des espaces.
- (Indice :
grep -i "TODO").
- Écrivez une seule ligne de commande qui cherche la chaîne de caractères “TODO” (insensible à la casse) dans tous les fichiers