07 - grep et find en profondeur
Ce que tu vas apprendre
- grep avec toutes ses options utiles (-r, -i, -n, -l, -v, -E, -c)
- find avec -name, -type, -mtime, -size, -exec, -delete
- Combiner grep et find pour des recherches chirurgicales
- ripgrep (rg) comme alternative moderne et rapide
- locate, which, whereis et type
Prerequisites
Connaitre les pipes et les redirections. Voir l'article sur les pipes.
La recherche, c'est 50% du boulot
Serieusement. Que tu debugges un bug, que tu cherches ou une variable est définie, ou que tu traques un fichier de config perdu, tu passes une bonne partie de ta journee a chercher des choses. Maitriser grep et find, c'est diviser ce temps par dix.
grep : chercher du texte
grep cherche un motif dans des fichiers ou dans un flux (via pipe). C'est probablement la commande que j'utilise le plus apres ls et cd.
Les options de base
bash# Chercher un mot dans un fichier
grep "error" application.log
# Les options indispensables
grep -i "error" app.log # Insensible a la casse (Error, ERROR, error)
grep -n "error" app.log # Affiche les numeros de ligne
grep -c "error" app.log # Compte le nombre d'occurrences
grep -l "TODO" src/*.ts # Affiche seulement les noms de fichiers
grep -v "debug" app.log # Inverse : lignes qui NE contiennent PAS "debug"
# Combiner
grep -in "error" app.log # Insensible a la casse + numeros de ligne
Recherche recursive
bash# Chercher dans tous les fichiers d'un repertoire
grep -r "TODO" src/
# Avec numeros de ligne (le plus courant)
grep -rn "TODO" src/
# Exclure des dossiers
grep -rn "import" src/ --exclude-dir=node_modules --exclude-dir=.git
# Exclure des types de fichiers
grep -rn "console.log" src/ --include="*.ts" --include="*.tsx"
# Seulement les noms de fichiers (utile quand il y a beaucoup de resultats)
grep -rl "deprecated" src/
Contexte autour des résultats
Quand tu cherches une erreur dans un log, tu veux souvent voir ce qu'il y a autour :
bash# 3 lignes apres chaque match
grep -A 3 "Exception" app.log
# 2 lignes avant chaque match
grep -B 2 "Exception" app.log
# 2 lignes avant ET apres (contexte)
grep -C 2 "Exception" app.log
# Exemple concret : voir le contexte d'une erreur dans les logs
$ grep -B 2 -A 5 "NullPointerException" server.log
2026-03-29 10:30:01 INFO Processing request /api/users/42
2026-03-29 10:30:01 DEBUG Fetching user from database
2026-03-29 10:30:01 ERROR NullPointerException
at UserService.getUser(UserService.java:42)
at UserController.handleRequest(UserController.java:18)
at Server.processRequest(Server.java:103)
at Server.main(Server.java:12)
grep avec des regex (-E)
-E active les expressions regulieres etendues (équivalent de egrep) :
bash# Chercher plusieurs mots (OU)
grep -E "error|warning|fatal" app.log
# Chercher un pattern
grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}" app.log # Lignes commencant par une date
grep -E "https?://[^ ]+" readme.md # URLs (http ou https)
grep -E "\b[A-Z]{2,}\b" code.ts # Mots tout en majuscules
# Chercher une adresse IP
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" access.log
# Extraire seulement le match (pas la ligne entiere)
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log | sort -u
# Liste unique des IPs dans les logs
Combiner grep avec des pipes
C'est là où grep devient vraiment puissant :
bash# Filtrer la sortie d'une commande
ps aux | grep "node"
docker ps | grep "running"
env | grep "PATH"
# Enchainer les filtres
cat access.log | grep "POST" | grep -v "healthcheck" | grep "500"
# Requetes POST qui ne sont pas des healthcheck et qui ont un code 500
# Compter les erreurs par heure
grep "ERROR" app.log | awk '{print $2}' | cut -d: -f1 | sort | uniq -c
# 142 08
# 253 09
# 37 10
# 253 erreurs entre 09:00 et 09:59
# Chercher un processus (en excluant le grep lui-meme)
ps aux | grep "[n]ode"
# L'astuce [n]ode : le grep ne se matche pas lui-meme
find : chercher des fichiers
On a vu find dans l'article sur les fichiers. Ici on va plus loin.
Recherches avancees
bash# Par nom avec des patterns
find . -name "*.test.ts" # Tests TypeScript
find . -iname "dockerfile*" # Insensible a la casse
find . -name "*.ts" -not -name "*.test.ts" # TS mais pas les tests
find . -name "*.ts" -o -name "*.tsx" # TS ou TSX (ou logique)
# Par type
find . -type f # Fichiers
find . -type d # Dossiers
find . -type l # Liens symboliques
find . -type f -empty # Fichiers vides
find . -type d -empty # Dossiers vides
# Par taille
find . -type f -size +100M # Plus de 100 Mo
find . -type f -size -1k # Moins de 1 Ko
find . -type f -size +10M -size -100M # Entre 10 et 100 Mo
# Par date
find . -mtime 0 # Modifie aujourd'hui
find . -mtime -7 # Modifie dans les 7 derniers jours
find . -mtime +30 # Pas modifie depuis 30 jours
find . -newer reference.txt # Plus recent que reference.txt
find . -mmin -60 # Modifie dans la derniere heure
# Par permissions
find . -perm 777 # Permissions exactement 777 (dangereux)
find . -perm -u+x # Executables par le proprietaire
find . -not -perm -o+r # Non lisibles par others
Actions sur les résultats
bash# Supprimer les fichiers trouves
find /tmp -name "*.tmp" -mtime +7 -delete
# Supprime les .tmp de plus de 7 jours dans /tmp
# Executer une commande sur chaque fichier
find . -name "*.sh" -exec chmod +x {} \;
# Rend executable chaque script shell
# Avec + au lieu de \; (plus performant, passe plusieurs fichiers a la fois)
find . -name "*.ts" -exec wc -l {} +
# Compte les lignes de tous les .ts
# Confirmation interactive
find . -name "*.log" -ok rm {} \;
# Demande confirmation avant chaque suppression
Combiner grep et find
Le combo grep + find est extremement puissant :
bash# Chercher "TODO" dans les fichiers TypeScript (en excluant node_modules)
find src -name "*.ts" -exec grep -Hn "TODO" {} +
# Equivalent plus lisible avec xargs
find src -name "*.ts" | xargs grep -Hn "TODO"
# Chercher dans les fichiers modifies cette semaine
find . -name "*.ts" -mtime -7 -exec grep -l "deprecated" {} +
# Trouver les fichiers de config qui contiennent "localhost"
find /etc -name "*.conf" -exec grep -l "localhost" {} + 2>/dev/null
# Remplacer dans tous les fichiers trouves
find src -name "*.ts" -exec sed -i 's/oldApi/newApi/g' {} +
ripgrep (rg) : l'alternative moderne
ripgrep (commande rg) est un grep moderne écrit en Rust. Il est plus rapide, respecte .gitignore par défaut, et a une sortie plus lisible :
bash# Installation
sudo apt install ripgrep # Debian/Ubuntu
brew install ripgrep # macOS
# Utilisation basique (recursif par defaut)
rg "TODO" src/
# Pas besoin de -r, pas besoin de --exclude-dir=node_modules
# Il lit .gitignore automatiquement
# Equivalences avec grep
grep -rn "pattern" src/ -> rg "pattern" src/
grep -ri "pattern" src/ -> rg -i "pattern" src/
grep -rl "pattern" src/ -> rg -l "pattern" src/
grep -rn "pattern" --include="*.ts" -> rg -t ts "pattern"
# Options specifiques a rg
rg "pattern" -t ts # Seulement les fichiers TypeScript
rg "pattern" -T test # Exclure les fichiers de test
rg "pattern" --hidden # Inclure les fichiers caches
rg "pattern" -g "!*.test.ts" # Exclure un pattern de fichiers
rg "pattern" -C 3 # 3 lignes de contexte
rg "pattern" --json # Sortie JSON (pour scripts)
rg "pattern" --stats # Statistiques de recherche
# Performance
$ time rg "import" --stats
# 2456 matches in 1.2s sur un projet de 50000 fichiers
# grep -r aurait pris 15 secondes sur le meme projet
Sur un gros projet, la différence de vitesse est flagrante. rg ignore automatiquement .git/, node_modules/, target/, et tout ce qui est dans .gitignore. Si tu ne devais installer qu'un seul outil supplementaire, c'est celui-la.
locate : la recherche instantanee
locate utilise une base de donnees pre-indexée. La recherche est quasi instantanee, mais les résultats peuvent etre en retard :
bash# Mettre a jour la base (fait automatiquement par cron, mais tu peux forcer)
sudo updatedb
# Chercher un fichier
locate nginx.conf
# /etc/nginx/nginx.conf
# /etc/nginx/nginx.conf.backup
# Insensible a la casse
locate -i dockerfile
locate est pratique pour les recherches système ("ou est installe postgres ?"), mais inutile pour les fichiers recents (la base n'est pas temps réel).
which, whereis, type : trouver des commandes
bash# which : ou est l'executable ?
$ which node
/usr/local/bin/node
$ which python3
/usr/bin/python3
# whereis : executable + man pages + sources
$ whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz
# type : comment le shell interprete la commande
$ type ls
ls is aliased to 'ls --color=auto'
$ type cd
cd is a shell builtin
$ type node
node is /usr/local/bin/node
# Utile pour debugger les conflits de PATH
$ type -a python
python is /usr/local/bin/python
python is /usr/bin/python
# Deux versions de python, laquelle est utilisee ?
Cas pratiques de la vraie vie
Quelques recherches que je fais régulièrement :
bash# Trouver toutes les variables d'environnement utilisees dans le code
rg 'process\.env\.\w+' src/ -o --no-filename | sort -u
# Trouver les fichiers les plus gros du projet (hors git et node_modules)
find . -type f -not -path "*/.git/*" -not -path "*/node_modules/*" -exec du -h {} + | sort -rh | head -20
# Chercher un port specifique dans toutes les configs
find /etc -name "*.conf" -exec grep -Hn "8080" {} + 2>/dev/null
# Trouver les imports inutilises (premier indice)
rg "^import" src/ -l | while read f; do
rg "^import .* from" "$f" -o | sed "s/import //" | sed "s/ from.*//" | while read var; do
count=$(rg "$var" "$f" -c)
[ "$count" -le 1 ] && echo "$f: $var possibly unused"
done
done
# Compter les lignes de code par langage
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.css" \) -not -path "*/node_modules/*" | while read f; do
echo "$(wc -l < "$f") $f"
done | sort -rn | head -20
Pour des workflows de recherche encore plus avances avec des outils comme fzf et fd, paltemps.fr propose des guides complémentaires.
Résumé
- grep :
-rnpour chercher recursivement,-ipour ignorer la casse,-Epour les regex - grep avec contexte :
-A(apres),-B(avant),-C(les deux) - find :
-name+-type+-mtimecouvrent 90% des cas,-execpour agir sur les résultats - ripgrep (
rg) est plus rapide et respecte.gitignore: installe-le whichpour trouver un executable,typepour comprendre comment le shell le voit- Combine grep + find + pipes pour des recherches chirurgicales
Precedent : Pipes et redirections | Suivant : Processus et jobs