Aller au contenu
Administration Linux medium

find : rechercher des fichiers efficacement

30 min de lecture

Quand on administre des serveurs ou des environnements de dev avec des arborescences profondes, on doit souvent retrouver vite un log énorme, un script perdu ou un répertoire précis. find parcourt le système de fichiers en temps réel et permet de sélectionner des fichiers (nom, type, taille, date, permissions) puis d'agir dessus (afficher, auditer, exécuter une commande, nettoyer).

  • Cibler des fichiers par nom, type, taille, date, permissions
  • Combiner des critères (AND/OR/NOT, parenthèses)
  • Appliquer une action en sécurité (-print → puis -exec/-delete)

find fait partie des commandes de recherche et de traitement de fichiers sous Linux. Chaque outil a sa spécialité :

CommandeSpécialitéQuand l'utiliser
findRechercher des fichiers par attributsTrouver par nom, taille, date, permissions
locateRecherche ultra-rapide par nomQuand la vitesse prime (base indexée)
grepRechercher dans le contenuTrouver une chaîne dans des fichiers
which / whereisLocaliser des exécutablesTrouver où est installé un programme
xargsExécuter des commandes en massePasser les résultats de find à une commande
awkTraiter des données tabulairesExtraire/transformer des colonnes
sedÉditer des fichiers en fluxRemplacer du texte, supprimer des lignes
cutExtraire des colonnesDécouper par délimiteur ou position

Combinaisons fréquentes :

Fenêtre de terminal
# find + grep : chercher un motif dans certains fichiers
find /var/log -name '*.log' -exec grep -l "error" {} +
# find + xargs : traitement en masse (robuste avec espaces)
find . -name '*.tmp' -print0 | xargs -0 rm -f
# locate + grep : filtrer les résultats de locate
locate '*.conf' | grep nginx

🧠 Modèle mental — Comment fonctionne find

find = Où chercher → Quoi garder → Quoi faire

Modèle mental find : Où chercher (dossier) → Quoi garder (filtres -name, -type, -size) → Quoi faire (actions -print, -delete, -exec)

Points clés

  • find parcourt un dossier et tous ses sous-dossiers
  • Il garde les fichiers qui matchent tes critères (nom, type, date, taille)
  • Plusieurs critères = ET (les deux doivent matcher)
  • Si tu utilises OU (-o), pense aux parenthèses
  • Tu peux exécuter une commande sur les fichiers trouvés (-exec)
  • Tu peux supprimer des fichiers (-delete) MAIS toujours vérifier avant avec -print

Règles d'or

1
Toujours tester avant d'utiliser des commandes destructrices Commence par -print, puis seulement ensuite -delete.
2
Gérer les noms "bizarres" Utilise les wildcards entre quote ou sans mais avec échappement. ex : '*.log' ou \*.log

Vocabulaire essentiel

-name '*.log'
Fichiers dont le nom correspond au motif
-type f / -type d
Fichier (f) ou dossier (d)
-mtime +7
Modifié il y a plus de 7 jours
-size +100M
Taille supérieure à 100 Mo
-maxdepth 2
Ne pas descendre plus de 2 niveaux
-print / -delete
Afficher les résultats / Supprimer
📚 Pour aller plus loin — 12 options avancées
-iname
Comme -name mais insensible à la casse
-path / -ipath
Pattern sur le chemin complet
-mmin -60
Modifié il y a moins de 60 minutes
-perm 644
Permissions exactes
-user / -group
Par propriétaire ou groupe
-prune
Exclure un sous-arbre
-xdev
Ne pas traverser les points de montage
-exec cmd {} \;
Exécuter pour chaque fichier
-exec cmd {} +
Exécuter en batch (plus rapide)
-ok cmd {} \;
Comme -exec avec confirmation
-printf FORMAT
Sortie formatée personnalisée
-quit
Arrêter au premier résultat

Contrairement à locate (index pré-calculé), find ne dépend pas d'une base : le résultat reflète l'état actuel du disque.

L'ordre des trois groupes n'est pas décoratif : find évalue les arguments de gauche à droite, et un filtre placé après une action ne filtre plus rien. C'est la cause numéro un des suppressions accidentelles, du type find /tmp -delete -name '*.tmp' qui vide /tmp en entier au lieu de cibler les .tmp. Retenez la règle : chemin, puis filtres, puis action, toujours dans cet ordre.

Fenêtre de terminal
find [CHEMIN...] [FILTRES...] [ACTIONS...]

La commande find suit toujours la même logique en trois étapes :

ÉtapeQuestionExemplesObligatoire ?
Où chercherDans quel dossier démarrer ?/var/log, ., /homeImplicite (défaut : .)
Quels résultats garderQuels fichiers correspondent à mes critères ?-name '*.log', -type f, -size +100MNon (par défaut : tout)
Quoi faireQuelle action effectuer sur les résultats ?-print, -delete, -exec rm {} +Non (par défaut : -print)

Où chercher (optionnel) : c'est le point de départ. find parcourt ce dossier et tous ses sous-dossiers récursivement. Sans chemin indiqué, GNU find utilise . (le répertoire courant), mais les implémentations BSD et macOS exigent un chemin explicite : prenez l'habitude de toujours l'écrire.

Quels résultats garder (optionnel) : ce sont les filtres. Sans filtre, find retourne tout. Plusieurs critères peuvent se combiner : par défaut ils sont liés par ET (tous doivent correspondre).

Quoi faire (optionnel) : c'est l'action finale. Sans action explicite, find affiche simplement les chemins (-print). Pour des actions destructrices (-delete, -exec rm), testez toujours avec -print d'abord.

Les filtres permettent de réduire les résultats aux fichiers qui vous intéressent. Voici les plus utilisés :

FiltreCe qu'il testeExemple
-name 'motif'Nom du fichier (sensible à la casse)-name '*.log'
-iname 'motif'Nom du fichier (insensible à la casse)-iname '*.LOG'

Toujours mettre le motif entre quotes : -name '*.log'. Sinon le shell interprète * avant find et vous obtenez des résultats inattendus.

FiltreCe qu'il testeExemple
-type fFichiers uniquement-type f
-type dDossiers uniquement-type d
-size +100MTaille supérieure à 100 Mo-size +100M
-size -1kTaille inférieure à 1 Ko-size -1k
-mtime -7Modifié il y a moins de 7 jours-mtime -7
-mtime +30Modifié il y a plus de 30 jours-mtime +30
-user aliceAppartient à l'utilisateur alice-user alice
-perm 644Permissions exactement 644-perm 644
-perm -644Au moins ces bits (lecture/écriture)-perm -644
-perm /222Au moins un bit d'écriture-perm /222

Note sur les tailles, le piège de l'arrondi : -size arrondit toujours à l'unité supérieure. Un fichier de 500 octets compte donc pour 1k, et find . -size -1k ne remonte que les fichiers de 0 octet, jamais les petits fichiers. Même effet avec M : -size -1M ne renvoie quasiment rien. Pour raisonner en taille réelle, utilisez l'unité c (octets) : find . -type f -size -1000c. Les unités disponibles sont b (blocs de 512 octets, valeur par défaut), c (octets), w (mots de 2 octets), k (kibioctets), M (mébioctets) et G (gibioctets) : ce sont des puissances de 1024, pas des mégaoctets décimaux.

Combiner les filtres, ET / OU / NON :

Par défaut, les filtres sont combinés avec ET (tous doivent correspondre) :

Fenêtre de terminal
# Fichiers .log ET de plus de 10 Mo (les deux conditions)
find /var/log -type f -name '*.log' -size +10M

Astuce : ajoutez -type f pour ne matcher que les fichiers (évite le bruit des répertoires).

Pour utiliser OU, ajoutez -o et des parenthèses (échappées) :

Fenêtre de terminal
# Fichiers .log OU .txt
find /var/log -type f \( -name '*.log' -o -name '*.txt' \)

Pourquoi \( et \) ? Le shell interprète les parenthèses nues. On les échappe (\( \)) ou on les met entre quotes ('(' ')').

Pour exclure par nom, utilisez ! ou -not :

Fenêtre de terminal
# Tous les fichiers SAUF ceux commençant par .git
find . -type f ! -name '.git*'

Attention : ceci n'exclut PAS le dossier .git/ du parcours. find y descend quand même et se contente de ne pas afficher les chemins correspondants, ce qui coûte du temps sur les gros dépôts. Pour vraiment ignorer un dossier, utilisez -prune :

Fenêtre de terminal
# Exclure le dossier .git de la recherche (correct)
find . -name .git -prune -o -type f -print

Une fois les fichiers filtrés, vous pouvez agir dessus. Les deux premières actions sont sans risque, les trois suivantes modifient le disque. La distinction importante se joue entre -delete et -exec rm : -delete est interne à find, il ne lance aucun processus et gère correctement les noms exotiques, mais il active automatiquement -depth, ce qui le rend incompatible avec -prune. Si votre commande contient -prune, passez par -exec rm {} + ou par un pipeline xargs.

ActionCe qu'elle faitExemple
-printAffiche le chemin (par défaut)-print
-lsAffiche en format ls -l-ls
-deleteSupprime le fichier-delete
-exec cmd {} \;Exécute cmd sur chaque fichier-exec chmod 644 {} \;
-exec cmd {} +Exécute cmd avec tous les fichiers-exec rm {} +

Règle d'or : toujours prévisualiser avant de détruire

Fenêtre de terminal
# DANGEREUX : supprime directement, sans contrôle
find /tmp -name '*.tmp' -delete
# SÛR : prévisualiser d'abord
find /tmp -name '*.tmp' -print
# Vérifier la liste, puis seulement :
find /tmp -name '*.tmp' -delete

Alternative robuste (gère les espaces et caractères spéciaux dans les noms) :

Fenêtre de terminal
find . -type f -name '*.tmp' -print0 | xargs -0 rm -f

-exec {} \; vs -exec {} + : la différence est importante :

  • \; : lance une commande par fichier (lent si beaucoup de fichiers)
  • + : regroupe les fichiers et lance une seule commande (rapide, recommandé)
Fenêtre de terminal
# Lent : 1000 fichiers = 1000 appels à chmod
find . -type f -exec chmod 644 {} \;
# Rapide : 1000 fichiers = quelques appels à chmod
find . -type f -exec chmod 644 {} +

Par défaut, find parcourt l'arborescence de haut en bas. Deux options modifient ce comportement :

-depth traite le contenu d'un dossier avant le dossier lui-même :

Fenêtre de terminal
# Sans -depth : /tmp est listé AVANT son contenu
find /tmp -type d
# Avec -depth : /tmp est listé APRÈS son contenu
find /tmp -depth -type d

C'est automatique avec -delete pour éviter de supprimer un dossier avant son contenu. Conséquence directe et souvent ignorée : puisque -depth neutralise -prune, une commande qui mélange -prune et -delete ne protège pas le dossier que vous croyiez exclure.

-prune stoppe la descente dans un dossier (utile pour exclure des répertoires) :

Fenêtre de terminal
# Exclure le dossier node_modules de la recherche
find . -name 'node_modules' -prune -o -name '*.js' -print
# Exclure plusieurs dossiers
find . \( -name 'node_modules' -o -name '.git' \) -prune -o -type f -print

Comment lire -prune : "Si tu trouves ce dossier, ne descends pas dedans (-prune), sinon (-o) applique le reste."

OptionEffetCas d'usage
-depthTraite enfants avant parentsSuppression récursive
-pruneN'entre pas dans le dossierExclure node_modules, .git
-maxdepth NLimite la profondeurfind . -maxdepth 1 (niveau courant)
-mindepth NIgnore les N premiers niveauxfind . -mindepth 2 (sous-dossiers)

Exemples pratiques :

Fenêtre de terminal
# Lister uniquement le contenu immédiat (pas de récursion)
find /var/log -maxdepth 1 -type f -name '*.log'
# Chercher à partir du 2e niveau (ignorer le dossier racine)
find . -mindepth 2 -type f -name '*.conf'
# Combiner les deux : chercher entre le niveau 2 et 4
find /home -mindepth 2 -maxdepth 4 -type d -name '.ssh'
# Supprimer des dossiers vides (depth nécessaire pour traiter enfants d'abord)
find /tmp -depth -type d -empty -delete
# Lister les fichiers du niveau courant uniquement (équivalent de ls)
find . -maxdepth 1 -type f

Ces quatre erreurs partagent une même racine : find reçoit autre chose que ce que vous avez tapé, parce que le shell est passé avant lui. Le réflexe de diagnostic est toujours le même : relancez la commande en préfixant par echo pour voir les arguments réellement transmis. Si echo find -name *.log affiche une liste de fichiers au lieu du motif, vous tenez le coupable.

ErreurCauseSolution
find -name *.log ne trouve rienLe shell a interprété * avant findMettre entre quotes : -name '*.log'
-o ne fonctionne pas comme prévuPriorité des opérateursAjouter des parenthèses : \( ... -o ... \)
"J'ai exclu .git mais find cherche dedans"! -name n'empêche pas la descenteUtiliser -prune : -name .git -prune -o ...
Résultats incluent des répertoiresPas de filtre -typeAjouter -type f pour les fichiers uniquement

Maintenant que vous comprenez la logique de find, voici dix modèles prêts à l'emploi. Chacun donne sa formule générale et un exemple concret.

-name compare uniquement le dernier composant du chemin, jamais le chemin complet. Chercher -name "syslog" remonte donc /var/log/syslog comme /var/log/journal/syslog, mais -name "log/syslog" ne remonte rien du tout. Pour raisonner sur le chemin entier, c'est -path qu'il faut employer.

Fenêtre de terminal
find <chemin> -name "<nom>" # formule
find /var/log -name "syslog" # exemple
  • chemin : point de départ de la recherche (défaut : .)
  • nom : nom exact ou motif glob

Le glob de -name diffère de celui du shell sur un point qui surprend : le * de find traverse les points, donc -name "*.log" remonte aussi les fichiers cachés comme .hidden.log. En revanche, il ne traverse jamais le séparateur /, ce qui garantit que le motif reste cantonné au nom de fichier.

Fenêtre de terminal
find <chemin> -name "*.ext" # formule
find . -name "*.log" # exemple
  • * : joker, n'importe quels caractères
  • toujours entre guillemets, sinon le shell interprète le *

Ajouter -type f n'est pas cosmétique : sans lui, un -exec ou un -delete s'applique aussi aux répertoires et aux liens symboliques qui portent le même motif. Le cas de -type l mérite une attention particulière : find teste le lien lui-même, pas sa cible, sauf si vous ajoutez l'option -L en tête de commande.

Fenêtre de terminal
find <chemin> -type <f|d|l> # formule
find /etc -type d -name "*.d" # exemple
  • f : fichier régulier, d : dossier, l : lien symbolique

C'est le filtre où l'arrondi à l'unité supérieure décrit plus haut fait le plus de dégâts. Pour un audit d'espace disque, -size +100M fonctionne parfaitement puisqu'on cherche des gros fichiers. Pour traquer les petits fichiers, passez obligatoirement en octets avec le suffixe c, sinon vous ne récupérerez que les fichiers vides.

Fenêtre de terminal
find <chemin> -type f -size <+|->N<c|k|M|G> # formule
find /var/log -type f -size +100M # exemple
  • +/- : plus grand / plus petit que
  • unités : c octets, k Ko, M Mo, G Go

-mtime raisonne en tranches de 24 heures, comptées à partir de l'instant où la commande démarre, pas depuis minuit. « Modifié il y a plus de 7 jours » signifie donc « il y a plus de 7 fois 24 heures », ce qui ne correspond pas à la semaine calendaire. Quand vous nettoyez des journaux avec une politique de rétention datée, ajoutez l'option -daystart pour aligner le calcul sur le début de la journée courante. Pour des durées courtes, -mmin travaille en minutes.

Fenêtre de terminal
find <chemin> -mtime <+|->N # formule
find /tmp -type f -mtime +30 # exemple
  • +N : modifié il y a plus de N jours
  • -N : modifié il y a moins de N jours

-exec lance directement le programme, sans passer par un shell. Cela protège des noms de fichiers hostiles, mais interdit aussi les tubes, les redirections et les jokers dans la commande exécutée : -exec grep motif {} > sortie.txt \; redirige la sortie de find, pas celle de grep. Pour du vrai shell, il faut expliciter -exec sh -c '...' _ {} \;. Variante prudente : -ok remplace -exec et demande une confirmation avant chaque exécution.

Fenêtre de terminal
find <chemin> <tests> -exec <cmd> {} \; # formule
find . -name "*.bak" -exec rm {} \; # exemple
  • {} : remplacé par le nom du fichier
  • \; : termine la commande (échappé)

Le gain de performance vient du nombre de processus créés : \; en lance un par fichier, + en lance un par paquet d'arguments tenant dans la limite du système. Deux réserves à connaître avant de généraliser. D'abord, {} doit être le dernier argument de la commande, ce qui exclut les invocations du type cp {} /destination. Ensuite, la sortie change : wc -l en mode + ajoute une ligne total, absente en mode \;.

Fenêtre de terminal
find <chemin> <tests> -exec <cmd> {} + # formule
find . -name "*.txt" -exec wc -l {} + # exemple
  • + : agrège les fichiers (comme xargs)

Le danger d'un pipeline find | xargs sans -print0 n'est pas théorique : xargs découpe sur les espaces et sur les sauts de ligne, or un nom de fichier Unix peut légalement contenir les deux. Un fichier nommé rapport annuel.pdf devient deux arguments, rapport et annuel.pdf, et la commande s'applique à des cibles qui n'existent pas ou, pire, qui existent ailleurs. Le caractère nul est le seul octet interdit dans un nom de fichier, donc le seul séparateur fiable.

Fenêtre de terminal
find <chemin> <tests> -print0 | xargs -0 <cmd> # formule
find . -name "*.pdf" -print0 | xargs -0 mv -t ~/backup/ # exemple
  • -print0 : sépare les résultats par un caractère nul
  • xargs -0 : lit ce même séparateur nul

Le contrôle en deux temps a une limite qu'il faut connaître : entre le -print et le -delete, l'arborescence a pu changer. Sur un serveur actif, préférez donc figer la liste dans un fichier, la relire, puis supprimer à partir de cette liste plutôt que de relancer find. Vérifiez aussi que le chemin de départ est bien celui que vous croyez, une faute de frappe sur /var au lieu de /var/tmp ne se rattrape pas.

Fenêtre de terminal
find <chemin> <tests> -print # étape 1 : visualiser
find <chemin> <tests> -delete # étape 2 : supprimer
  • Jamais -delete sans avoir lancé -print d'abord.

La construction se lit comme un aiguillage : condition -prune -o tests -print. Quand la condition est vraie, -prune renvoie vrai, le -o court-circuite la suite et find n'entre pas dans le dossier. Le -print final est obligatoire ici : sans lui, l'action -print implicite s'appliquerait aussi à la branche -prune et les dossiers exclus s'afficheraient malgré tout. C'est l'erreur la plus fréquente sur cette syntaxe.

Fenêtre de terminal
find <chemin> -path "*/<dossier>" -prune -o <tests> -print # formule
find . -path "./node_modules" -prune -o -name "*.js" -print # exemple
  • -prune : arrête la descente dans le dossier ciblé
  • -o : applique les tests au reste de l'arborescence

Six erreurs reviennent constamment avec find. Certaines sont destructrices, -delete ne pardonne pas.

Fenêtre de terminal
find . -name "Report.txt" # INCORRECT : ne trouve pas "report.txt"

Symptôme : la recherche ne renvoie rien alors que le fichier existe. Cause : -name distingue les majuscules des minuscules.

Fenêtre de terminal
find . -iname "report.txt" # CORRECT : -iname ignore la casse
Fenêtre de terminal
find . -name "*.txt" | xargs rm # INCORRECT : casse sur "mon fichier.txt"

Symptôme : erreur No such file ou suppression des mauvais fichiers. Cause : xargs découpe sur les espaces.

Fenêtre de terminal
find . -name "*.txt" -print0 | xargs -0 rm # CORRECT : séparateur nul
Fenêtre de terminal
find . -name "*.log" -o -name "*.txt" -mtime +7 # INCORRECT : -mtime ne s'applique qu'aux .txt

Symptôme : -mtime ne filtre qu'une partie des résultats. Cause : la précédence des opérateurs groupe -mtime avec le second -name.

Fenêtre de terminal
find . \( -name "*.log" -o -name "*.txt" \) -mtime +7 # CORRECT : parenthèses échappées
Fenêtre de terminal
find /var -name "*.tmp" -delete # INCORRECT : exécuté directement, sans contrôle

Symptôme : des fichiers importants supprimés par erreur. Cause : un motif trop large appliqué sans prévisualisation.

Fenêtre de terminal
find /var -name "*.tmp" -print # CORRECT : vérifier d'abord, puis remplacer -print par -delete
Fenêtre de terminal
find . -mtime -1 # INCORRECT : ne reflète pas la « date de création »

Symptôme : des fichiers copiés apparaissent comme anciens. Cause : cp préserve parfois le mtime d'origine, qui reste la date de modification du contenu. Le ctime (date de changement de l'inode) est alors la bonne piste, puisqu'il se met à jour à chaque copie, chaque chmod et chaque renommage.

Fenêtre de terminal
# -mtime = contenu, -ctime = métadonnées de l'inode, -atime = dernier accès
find . -ctime -1

Une nuance à connaître : les systèmes de fichiers modernes (ext4, XFS, Btrfs) enregistrent bien une date de création (birth time), lisible avec stat --printf='%w\n' fichier. Mais find ne sait pas toujours la lire, la prise en charge du prédicat -newerBt dépend de la façon dont le binaire a été compilé. Sur les paquets Debian et Ubuntu courants, la commande renvoie This system does not provide a way to find the birth time of a file : ne construisez pas de script de rétention sur cette date sans l'avoir testée sur la machine cible.

Fenêtre de terminal
find . -name ".*\.log$" # INCORRECT : ne renvoie rien

Symptôme : aucun résultat. Cause : -name utilise des globs (*, ?), pas des expressions régulières.

Fenêtre de terminal
find . -regex ".*\.log$" # CORRECT : -regex pour une vraie regex (ou simplement -name "*.log")

Rien ne remplace la pratique. Créez l'environnement de test ci-dessous, puis déroulez les huit étapes. À la fin, nettoyez avec rm -rf ~/find-lab.

Ce script crée une arborescence dans ~/find-lab avec des fichiers de tailles, dates et permissions variées, y compris des noms contenant des espaces.

Fenêtre de terminal
# Créer le lab
mkdir -p ~/find-lab/{logs,config,data,backup}
cd ~/find-lab
# Fichiers logs de différentes tailles
dd if=/dev/zero of=logs/app.log bs=1M count=5 2>/dev/null
dd if=/dev/zero of=logs/error.log bs=1K count=100 2>/dev/null
dd if=/dev/zero of=logs/debug.log bs=1M count=20 2>/dev/null
# Fichiers config
echo "port=8080" > config/app.conf
echo "debug=true" > config/debug.conf
# Fichiers avec espaces dans le nom
touch "data/mon fichier.txt"
touch "data/rapport 2024.pdf"
# Fichiers avec des dates différentes
touch -d "30 days ago" backup/old-backup.tar
touch -d "7 days ago" backup/weekly.tar
touch backup/daily.tar
# Permissions variées
chmod 777 logs/debug.log
chmod 644 config/app.conf
echo "Lab créé dans ~/find-lab"
ls -laR ~/find-lab

Chaque étape ajoute un filtre ou une action à la précédente, jusqu'à la suppression contrôlée de l'étape 8. Comparez systématiquement le nombre de lignes renvoyées avec ce que contient réellement le lab : c'est en constatant qu'une commande remonte plus de résultats que prévu qu'on repère un filtre mal placé. Les étapes 7 et 8 sont les plus importantes, elles couvrent les deux situations qui cassent le plus souvent des scripts en production, les noms avec espaces et les suppressions non vérifiées.

  1. Trouver tous les fichiers .log. Listez tous les fichiers d'extension .log du lab.

    Fenêtre de terminal
    find ~/find-lab -name "*.log"

    -name utilise un motif glob ; * reconnaît n'importe quels caractères. Pour ignorer la casse : find ~/find-lab -iname "*.LOG".

  2. Filtrer par taille. Trouvez les fichiers de plus de 1 Mo.

    Fenêtre de terminal
    find ~/find-lab -type f -size +1M

    +1M signifie « plus de 1 mégaoctet », le + indique « supérieur à ».

  3. Fichiers anciens. Trouvez les fichiers modifiés il y a plus de 7 jours.

    Fenêtre de terminal
    find ~/find-lab -type f -mtime +7

    +7 signifie « modifié il y a plus de 7 jours » ; -7 serait « moins de 7 jours ».

  4. Combiner taille ET date. Trouvez les fichiers de plus de 1 Mo modifiés il y a moins de 1 jour.

    Fenêtre de terminal
    find ~/find-lab -type f -size +1M -mtime -1

    Par défaut, les critères se combinent en ET, inutile d'écrire -a.

  5. Fichiers .log OU .conf. Trouvez les fichiers .log ou .conf.

    Fenêtre de terminal
    find ~/find-lab \( -name "*.log" -o -name "*.conf" \)

    -o est le OU ; les parenthèses échappées (\( \)) groupent les conditions.

  6. Exécuter une commande sur chaque fichier. Affichez la taille lisible de chaque .log.

    Fenêtre de terminal
    find ~/find-lab -name "*.log" -exec ls -lh {} \;

    {} est remplacé par le nom du fichier ; \; termine la commande. Version plus rapide : -exec ls -lh {} +.

  7. Gérer les noms avec espaces. Listez en détail les fichiers du dossier data/.

    Fenêtre de terminal
    find ~/find-lab/data -type f -print0 | xargs -0 ls -la

    -print0 et xargs -0 utilisent le caractère nul : mon fichier.txt reste un seul argument.

  8. Supprimer en sécurité. Supprimez les .tar de plus de 7 jours, visualisez d'abord, supprimez ensuite.

    Fenêtre de terminal
    # Étape 1 : visualiser
    find ~/find-lab/backup -name "*.tar" -mtime +7 -print
    # Étape 2 : une fois la liste vérifiée
    find ~/find-lab/backup -name "*.tar" -mtime +7 -delete

    Ne mettez jamais -delete sans avoir contrôlé la liste avec -print.

Huit exercices pour valider votre maîtrise. Cherchez d'abord par vous-même, puis dépliez la solution pour vous corriger.

Ces trois exercices portent sur un seul filtre à la fois. Si vous bloquez, la réponse tient toujours dans une option courte du type -maxdepth, -empty ou -mtime : cherchez l'option dédiée plutôt que de composer une expression complexe, find en propose presque toujours une.

Exercice 1 - Trouver les fichiers .conf. Listez les fichiers .conf directement dans /etc, sans descendre dans les sous-dossiers. Indice : -maxdepth 1 limite la profondeur.

Voir la solution
Fenêtre de terminal
find /etc -maxdepth 1 -name "*.conf"

-maxdepth 1 restreint la recherche au dossier de départ, sans récursion.

Exercice 2 - Fichiers vides. Trouvez tous les fichiers vides (0 octet) dans /tmp. Indice : il existe une option dédiée aux fichiers vides.

Voir la solution
Fenêtre de terminal
find /tmp -type f -empty

-empty est plus lisible que -size 0 et fonctionne aussi pour les dossiers vides.

Exercice 3 - Fichiers récents. Trouvez les fichiers de votre dossier personnel modifiés dans les dernières 24 heures. Indice : -mtime avec un nombre négatif.

Voir la solution
Fenêtre de terminal
find ~ -type f -mtime -1

-mtime -1 signifie « modifié il y a moins de 1 jour ».

On passe ici à la combinaison de critères, et c'est la priorité des opérateurs qui piège. Retenez que le ET implicite lie plus fort que le -o : dès qu'un OU apparaît dans une commande qui contient d'autres filtres, les parenthèses échappées deviennent obligatoires sous peine de résultat silencieusement faux.

Exercice 4 - Taille et extension. Trouvez les fichiers .log de plus de 10 Mo dans /var/log. Indice : combinez -name et -size.

Voir la solution
Fenêtre de terminal
find /var/log -type f -name "*.log" -size +10M

Les critères se combinent en ET par défaut, inutile d'écrire -a.

Exercice 5 - OU logique. Trouvez les fichiers .jpg ou .png dans ~/Images. Indice : -o avec des parenthèses échappées.

Voir la solution
Fenêtre de terminal
find ~/Images -type f \( -name "*.jpg" -o -name "*.png" \)

Les parenthèses groupent le OU ; sans elles, la logique serait incorrecte.

À ce stade, find ne sert plus à regarder mais à agir. Les deux exercices opposent les deux mécanismes disponibles, -exec intégré et pipeline xargs. Sur des arborescences volumineuses, mesurez la différence avec time : l'écart entre \; et + se compte en secondes dès quelques milliers de fichiers.

Exercice 6 - Exécuter ls -lh sur les résultats. Affichez la taille lisible de chaque fichier de plus de 100 Mo dans /var. Indice : -exec avec ls -lh.

Voir la solution
Fenêtre de terminal
find /var -type f -size +100M -exec ls -lh {} \;

{} est remplacé par chaque fichier trouvé ; \; termine la commande.

Exercice 7 - Pipeline xargs sécurisé. Comptez le nombre total de lignes de tous les fichiers .py d'un projet, même avec des espaces dans les noms. Indice : -print0 puis xargs -0.

Voir la solution
Fenêtre de terminal
find . -name "*.py" -print0 | xargs -0 wc -l

-print0 et xargs -0 gèrent les noms avec espaces sans risque.

Le dernier exercice est le seul destructeur, et c'est volontaire. Lancez-le d'abord sur un répertoire jetable de votre création, jamais directement sur /tmp d'un serveur partagé : d'autres processus y déposent des fichiers de travail dont la disparition provoque des pannes difficiles à relier à votre commande.

Exercice 8 - Nettoyage sécurisé. Supprimez les fichiers .tmp de plus de 7 jours dans /tmp, en montrant d'abord ce qui sera supprimé. Indice : deux commandes, -print puis -delete.

Voir la solution
Fenêtre de terminal
# Étape 1 : prévisualiser
find /tmp -name "*.tmp" -mtime +7 -print
# Étape 2 : une fois la liste vérifiée
find /tmp -name "*.tmp" -mtime +7 -delete

Toujours prévisualiser avec -print avant d'utiliser -delete.

Quand find ne renvoie pas ce qu'on attend, le problème vient le plus souvent du quoting ou des permissions. Voici comment diagnostiquer.

La méthode consiste à retirer les filtres un par un jusqu'à obtenir des résultats, puis à remettre le dernier retiré : c'est lui le fautif. La dernière commande du bloc mérite un mot, elle redirige stderr vers stdout pour filtrer les messages Permission denied. Sans cette redirection 2>&1, grep ne voit rien car les erreurs de find ne passent pas par la sortie standard.

Fenêtre de terminal
# Retirer les filtres un par un pour isoler le problème
find /chemin
# Ajouter -print explicite pour voir ce qui est traité
find /chemin -name "*.log" -print
# Vérifier le quoting (le shell peut interpréter * avant find)
find /chemin -name "*.log"
# Repérer les dossiers où find n'a pas les droits
find /chemin 2>&1 | grep -i permission

La colonne Solution propose parfois 2>/dev/null, à manier avec discernement : masquer les erreurs de permission est confortable pour une recherche interactive, mais dans un script cela cache aussi les vraies pannes, disque plein ou point de montage disparu. Dans un script planifié, laissez les erreurs visibles et traitez plutôt le code de retour de find, qui vaut 1 dès qu'un répertoire n'a pas pu être parcouru.

Message d'erreurCause probableSolution
find: '/root': Permission deniedPas de droit de lecture sur le dossierUtiliser sudo, ou masquer les erreurs : find /chemin 2>/dev/null
find: '/chemin': No such file or directoryLe chemin de départ n'existe pasVérifier le chemin avec ls, contrôler l'orthographe
find: missing argument to '-exec'\; ou + oublié en fin de -execTerminer la commande : -exec ls -l {} \;

Les quatre tableaux qui suivent servent de rappel une fois le guide assimilé. Ils sont organisés dans l'ordre où l'on construit une commande, parcours puis filtres puis actions puis composition, ce qui permet de les lire de haut en bas en écrivant.

Ces options se placent avant le chemin ou juste après, et elles conditionnent l'étendue du parcours plutôt que la sélection. -xdev est celle qu'on oublie le plus souvent : sans elle, un find / traverse les montages NFS, les partitions de sauvegarde et /proc, ce qui transforme une recherche de trente secondes en plusieurs minutes.

OptionRôleExemple
-maxdepth NLimite la profondeur de recherchefind . -maxdepth 2 -name "*.txt"
-mindepth NIgnore les N premiers niveauxfind . -mindepth 1 -type d
-LSuit les liens symboliquesfind -L /opt -name "*.conf"
-xdevReste sur le même système de fichiersfind / -xdev -size +100M

Les filtres se cumulent librement et se combinent en ET implicite. Deux lignes valent une attention particulière : -path compare le chemin complet là où -name ne voit que le nom, et -newer compare à la date de modification d'un fichier témoin, ce qui donne un moyen pratique de trouver tout ce qui a changé depuis un déploiement en posant un fichier repère avant l'opération.

FiltreRôleExemple
-name "*.ext"Nom avec glob (sensible à la casse)-name "*.log"
-iname "*.ext"Nom avec glob (insensible à la casse)-iname "*.JPG"
-type f / -type dFichiers / dossiers uniquement-type f
-path "*pattern*"Motif sur le chemin complet-path "*/test/*"
-size +100M / -size -1kPlus grand / plus petit que-size +1G
-emptyFichiers ou dossiers vides-type f -empty
-mtime +7 / -mtime -1Modifié il y a plus / moins de N jours-mtime +30
-newer fichierPlus récent qu'un fichier de référence-newer ref.txt
-perm 644Permissions exactes-perm 755
-user bobAppartient à un utilisateur-user root

Une seule action par commande dans la pratique courante, mais rien ne l'impose : find . -name '*.log' -print -delete affiche puis supprime dans le même passage. Évitez cette écriture, elle donne l'illusion d'un contrôle alors que la suppression a déjà eu lieu quand vous lisez la sortie.

ActionRôleExemple
-printAffiche le chemin (défaut)-print
-print0Affiche séparé par un caractère nul-print0 | xargs -0
-exec cmd {} \;Exécute la commande pour chaque fichier-exec rm {} \;
-exec cmd {} +Exécute la commande en lot-exec ls {} +
-deleteSupprime les fichiers trouvés-mtime +30 -delete

La règle de priorité tient en une phrase : le ET (-a, implicite) lie plus fort que le OU (-o), exactement comme la multiplication lie plus fort que l'addition. Dès qu'un -o cohabite avec un autre filtre, les parenthèses échappées sont obligatoires, sinon find regroupe les termes autrement que vous ne le lisez.

OpérateurRôleExemple
-aET (implicite entre deux critères)-name "*.log" -a -size +1M
-oOU-name "*.jpg" -o -name "*.png"
\( … \)Groupement de conditions\( -name "*.jpg" -o -name "*.png" \)
-pruneExclut un sous-arbre du parcours-path "./vendor" -prune

Vous maîtrisez find lorsque vous pouvez cocher chacun de ces points :

  • Je sais utiliser -name et -iname
  • Je sais filtrer par -type (f, d, l)
  • Je sais utiliser -size avec +/- et les unités
  • Je sais utiliser -mtime, -ctime, -atime
  • Je sais combiner des critères avec -o et des parenthèses
  • Je sais utiliser -exec {} \; et -exec {} +
  • Je sais sécuriser un pipeline avec -print0 \| xargs -0
  • Je sais sécuriser -delete en lançant -print d'abord
  • Je sais exclure un dossier avec -prune
  • Je sais diagnostiquer une recherche qui ne renvoie rien

La commande find est un outil essentiel pour quiconque travaille régulièrement en ligne de commande. Grâce à sa souplesse et à sa richesse fonctionnelle, elle permet de retrouver, filtrer et manipuler efficacement des fichiers dans n'importe quelle arborescence. Que ce soit pour une recherche rapide, un nettoyage automatisé ou un audit de permissions, la maîtrise de find fait gagner un temps précieux et renforce la qualité de vos scripts et interventions système.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn