Introduction
La commande find
permet de retrouver des fichiers à partir de certains
critères. Quelques exemples pratiques, notamment avec des expressions régulières, elles sont trop peu utilisées mais si puissantes.
La commande grep
quant à elle permet d’explorer un ou une série de fichiers
d’un même répertoire à la recherche de texte satisfaisant une expression
régulière donnée. grep
est l’acronyme de "Globally search for a Regular Expression and Print matching lines".
La commande find et ses options
Syntaxe de la commande find
find répertoire critères
Quelques critères de recherche les plus courants :
-name |
recherche sur le nom du fichier |
-perm |
recherche sur les droits d’accès du fichier |
-user |
recherche sur le propriétaire du fichier |
-group |
recherche sur le groupe auquel appartient au fichier |
-type |
recherche sur le type (d=répertoire, l=lien, f=fichier normal) |
-size |
recherche par taille de fichier |
-mtime |
recherche par date de dernière modification du fichier |
-ctime |
recherche par date de création du fichier |
Il est possible de combiner les critères avec des opérateurs logiques :
\( critere1 critere2 \)
ou\( critere1 -a critere2 \)
:ET
logique (AND
)\( ! critere \)
:NON
logique (NOT
)\( critere1 -o critere2 \)
:OU
logique (OR
)
La commande find
est utilisée au moins avec l’option -print
. Sans cette option minimale,
même en cas de réussite dans la recherche, find
n’affiche rien
à la sortie standard.
La commande find
est récursive, les répertoires et les sous répertoires sont
scrutés par cette commande.
Recherche par nom de fichier
Option -name
Rechercher tous les fichiers se terminant par .c
dans le répertoire /usr
:
find /usr -name *.c -print
/usr/share/bison/yacc.c /usr/share/bison/glr.c …
Rechercher dans le répertoire courant les fichiers avec l’extension .jpg
ou l’extension .gif
mais ne contenant
pas le mot gimp
dans le nom :
find . \( ! -name "*gimp*" -a \( -name "*.jpg" -o -name "*.gif" \) \) -print | sort
… ./images/conception-html-dynamique-suppression-document.write-01.jpg ./images/conception-html-equations-math-mathjax-asciimath-01.jpg ./images/google-analytics-optimisation-mesure-audience-01.jpg ./images/google-analytics-optimisation-mesure-audience-02.jpg …
Par défaut les résultats ne sont pas triés, c’est pourquoi ci-dessus sort
est appelé sur la sortie de la commande find
.
Pour spécifier le répertoire courant : find . < critères >
Recherche par dates
Option -mtime +/-
Rechercher les fichiers *.js
ou *.css
modifiés il y a moins de 2 jours :
find . -mtime -2 -a \( -name "*.js" -o -name "*.css" \) -print
./css/style-df.css ./css/style.css ./js/resources/nohttp.js
Option -ctime +/-
Rechercher les fichiers *.json
créés il y a plus de 30 jours dans le répertoire $LOG
:
find $LOG -ctime +30 -name "*.json" | sort
./postgresql-9.6-setup-installation-rapide_20200929030800.json ./postgresql-9.6-setup-installation-rapide_20200929023720.json …
L’option -mtime -2
est en fait équivalente à -48h
, l’option -ctime +30
à +30 × 24h
: find
se base par défaut sur la date et l’heure courante.
Utiliser daystart
pour se baser réellement sur le nombre de jours sans prendre en compte l’heure courante.
find . -daystart -mtime -2 -name "*.html"
Recherche suivant la taille
Option -size +/-
Identifier dans une arborescence les fichiers *.html
dont la taille est supérieure à 50K (soit 100 blocs de 512o) :
find . -size +100 -name "*.html" -print
./influxdb-v1.7-architecture-installation-configuration-utilisation.html ./sybase-ase-iq-comparaison.html …
Dans la pratique, l’unité (k | M | G
) est spécifiée pour ne pas calculer les multiples de 512 octets.
find . -size +50k -name "*.html" -print
find . -size +100M -print
find . -size +2G -print
Redirection des messages d’erreur
Les droits d’accès ne sont pas toujours autorisés pour certains répertoires,
par conséquent, la commande find
peut générer un grand nombre de messages
d’erreur (permission denied, etc.). Pour éviter ceci, rediriger les messages d’erreur vers un fichier "poubelle" (ex /dev/null
), les
messages d’erreur sont alors perdus. Il est toutefois possible de sauvegarder
ces erreurs dans un fichier régulier.
Exemple :
find . \( -name a.out -o -name "*.c" \) -print > /dev/null
find et l’option exec
L’option -print
est une option que l’on passe à la commande find
pour
afficher les résultats à la sortie standard. L’option -exec
est disponible dans la commande find
et
elle est exclusive de l’option -print
.
Lorsque la commande find
est couplée à l’option exec
, il est alors possible
d’exécuter une commande sur les fichiers trouvés par la commande find
.
find repertoire critères -exec commande {} \;
La sortie de la commande find
avec l’option -print
est très basique, voire trop :
find . -type f -size +100k -print
./sybase-replication-server-guide-pratique.pdf ./images/gimp-supprimer-couleur-arriere-plan-fond-09.jpg …
Avec l’option -exec
, la commande find
est usuellement combinée avec la commande ls
pour afficher plus de détails sur les
résultats :
find . -type f -size +100k -exec ls -lh {} \; 2> /dev/null
-rw-r--r-- 1 sqlpac wapp 118K Jun 15 11:34 ./sybase-replication-server-guide-pratique.pdf -rw-r--r-- 1 sqlpac wapp 104K Jun 15 11:33 ./images/gimp-supprimer-couleur-arriere-plan-fond-09.jpg …
Autres exemples courants :
Supprimer tous les fichiers core avec la commande rm
:
find . -name core -exec rm {} \;
Supprimer tous les fichiers *.json
créés il y a plus de 10 jours dans le répertoire $LOG
avec la commande rm
:
find $LOG -name "*.json" -ctime +10 -exec rm {} \;
Des exemples encore plus concrets :
On recherche dans un répertoire et ses sous répertoires la liste des fichiers *.htm, *.html, *.inc, *.php, *.css, *.json, *.xml
pour lesquels
l’encodage est iso-8859-1. L’encodage est donné par la commande file
et l’option -i
:
find . -type f \( -name "*.html" -o -name "*.htm" -o -name "*.json" -o -name "*.php" -o -name "*.inc" -o -name "*.x ml" -o -name "*.css" -o -name "*.xml" \) -exec file -i {} \; | grep -i 'iso-8859-1'
./admpmgportal/config.inc: text/x-php; charset=iso-8859-1 ./admpmgportal/include/rules.inc: text/x-php; charset=iso-8859-1 ./admpmgportal/include/treeview.inc: text/html; charset=iso-8859-1...
Pour retrouver tous les fichiers non binaires contenant la chaîne de caractères '79.13'
:
find . -type f -exec grep -Il '79\.13' {} \;
./redis/dba/srvrdisqlpac/cfg/srvrdisqlpac.conf ...
Bien utile pour rechercher des codages (adresses IP, fonctions…) dans une arborescence, quel que soit le type de fichier du moment
qu’il ne s’agisse pas d’un fichier binaire. L’option -I
dans la commande grep
écarte les fichiers binaires.
La commande find et les expressions régulières (-regex et -regextype)
Option -regex
L’exemple précédent n’est pas très élégant ( -o -name "*.css" -o -name "*.php
… ).
Les expressions régulières sont implémentées dans la commande find
avec l’option -regex
.
Le code devient bien plus lisible avec cette fonctionnalité.
find . -regex '.*\.\(css\|htm\|html\|inc\|js\|json\|php\|xml\)' -exec file -i {} \;
Plusieurs librairies existent pour les expressions régulières (posix, GNU awk…), librairies pour lesquelles les syntaxes des expressions régulières peuvent différer.
L’option -regextype
donne la librairie à utiliser pour l’expression régulière : un exemple de recherche des fichiers *.txt
et *.inc
avec la librairie posix-basic
.
find -regextype posix-basic -regex ".*\(txt\|inc\)" -print
Les librairies et syntaxes des expressions régulières sont nombreuses et ne sont pas détaillées ici, ce n’est pas l’objet de cet article.
Une petite astuce pour retrouver les librairies disponibles sur la plateforme utilisée : appeler une commande find
avec une option -regextype
invalide.
find .-regextype dummy
find: Unknown regular expression type `dummy'; valid types are `findutils-default', `awk', `egrep', `ed', `emacs', `gnu-awk', `grep', `posix-awk', `posix-basic', `posix-egrep', `posix-extended', `posix-minimal-basic', `sed'.
Pour gérer l’insensibilité à la casse dans les expressions régulières, utiliser option -iregex
.
find -iregex ".*\.\(txt\)' -print
./README.TXT
Combinaison des commandes find et xargs
Cette fois, on recherche l’appel de la fonction PHP ereg_replace
dans le code source des fichiers *.php
et *.inc
.
find . -type f \( -name "*.php" -o -name "*.inc" \) -print | xargs grep -ni "ereg_replace"
... ./sqlpacv2/prp_article.php5:216: $caption = ereg_replace("\.","",_USRDIR_DOC)."/".$datadoc[1]["fichier"]; ./sqlpacv2/prp_glossaire.php5:95: $caption = ereg_replace("\.","",__USRDIR_DOC)."/".$article["fichier"];
La commande xargs
exécute une commande echo
/cat
sur le fichier retourné par l’option -print
de la commande find
.
Ainsi la commande qui suit xargs
(grep
dans l’exemple ci-dessus) est exécutée sur le fichier.
Find et les liens
Option -xtype
La commande find
est très pratique pour retrouver les liens "cassés" (broken links) :
find . -xtype l -exec ls -ll {} \;
lrwxrwxrwx 1 sqlpac wapp 26 Sep 3 14:33 ./postmenu.php -> ../../engines/postmenu.php
Si l’option -xtype
n’est pas disponible sur la plateforme utilisée, utiliser la commande test
:
find . -type l ! -exec test -e {} \; -exec ls -ll {} \;
lrwxrwxrwx 1 sqlpac wapp 26 Sep 3 14:33 ./postmenu.php -> ../../engines/postmenu.php
Un exemple bien utile : calculer la taille des images dans un répertoire
En une ligne de commande en combinant find
et awk
, pour calculer la taille des images dans un répertoire :
find . -regex '.*\.\(png\|gif\|jpg\|jpeg\)' -exec ls -l {} \; | \ awk 'BEGIN {sum=0} {sum+=$5} END { printf("%.2f %s\n",sum/1024000,"Mb") }'
18.16 Mb
La commande grep et ses options
Syntaxe de la commande grep
grep -option(s) expression fichier(s)
Quelques options usuelles :
-v |
affiche les lignes ne satisfaisant pas l’expression |
-c |
compte le nombre de lignes satisfaisant l’expression sans afficher les lignes |
-n |
affiche la ligne et le numéro de la ligne satisfaisant l’expression |
-i |
ignorer la casse |
Some examples :
Rechercher des tableaux (balises HTML <table>
) dans les fichiers *.html
:
grep "<table" *.html
… sybase-iq-12.7-migration-ase-vers-iq.html: <table class="alt- r-brdr rco-"> sybase-iq-12.7-migration-ase-vers-iq.html: <table> sybase-iq-12.7-migration-ase-vers-iq.html: <table class="alt- r-brdr"> …
Avec les numéros de lignes et sans sensibilité à la casse :
grep -ni "<table" *.html
… sybase-iq-12.7-migration-ase-vers-iq.html:232: <table class="alt- r-brdr rco-"> sybase-iq-12.7-migration-ase-vers-iq.html:512: <table> sybase-iq-12.7-migration-ase-vers-iq.html:661: <table class="alt- r-brdr"> …
Juste le nombre d’occurences en ignorant la casse :
grep -ci "<table" *.html
… sybase-iq-12.7-migration-ase-vers-iq.html:6 … sybase-iq-index-cardinalite-sp_dba_helpcolumn.html:0 …
Les résultats en sortie de la commande grep
sont séparés par :
, bien pratique
pour traiter rapidement les résultats avec l’utilitaire awk
.
grep -ci "<table" *.html | \ awk -F":" 'BEGIN { hf=0; tb=0; } { if ($2 != 0) { hf++; tb +=$2 } } END { print tb" tableaux dans "hf" fichiers"}'
549 tableaux dans 187 fichiers
Les expressions régulières avec grep
L’option -E
donne une expression régulière à la commande grep
.
Pour rechercher la chaîne de caractères mysql_connect
, mysql_query
et mysql_close
dans des fichiers php avec les numéros de ligne :
grep -ni -E "mysql_connect|mysql_query|mysql_close" *.php
cls_database_myisam.php5:59: $objRessource = mysql_connect(_SGBD_SERVER,_SGBD_USER,$pwdUnCrypted); cls_database_myisam.php:81: $ret=mysql_close($objRessource); cls_database_myisam.php5:108: $return = mysql_query($queryString,$objRessource); cls_database_myisam.php5:114: $reserrors = mysql_query('select @errno as errno , @errmsg as errmsg' cls_database_myisam.php5:341: $resultPlan=mysql_query("EXPLAIN ".$query,$objRessource);
La commande egrep
n’est ni plus ni moins que la commande grep
avec l’option -E
:
egrep -ni "mysql_connect|mysql_query|mysql_close" *.php
Une autre syntaxe possible plus élégante :
egrep -ni "mysql_(connect|query|close)" *.php
La liste des termes de l’expression régulière est parfois longue pour une seule ligne de commande,
c’est pourquoi les termes peuvent être définis dans un fichier texte, fichier donné à la commande grep
avec l’option -f
.
grep -ni -f regex.txt *.php
regex.txt
mysql_connect
mysql_query
Comme pour la commande find
, la commande grep
autorise l’utilisation de différentes syntaxes d’expressions régulières.
- Option
-E
: expressions régulières étendues (ERE, Extended Regular Expressions) - Option
-G
: expressions régulières basiques (BRE, Basic Regular Expressions) - Option
-P
: expressions régulières PERL (PRE, Perl Regular Expressions)
Quelques autres exemples :
Rechercher des lignes commençant par une étoile, le caractère ^
dans l’expression régulière signifiant "commençant par" :
grep -ni -E "^ \*" *.php
Rechercher des lignes finissant par un point virgule , le caractère $
dans l’expression régulière correspondant à une fin de ligne :
grep -ni -E "$;" *.php
En reprenant les premiers exemples, rechercher tous les tableaux dans les fichiers *.html
ayant la classe CSS rco-
et/ou r-brdr
:
egrep -ni "<table.*class.*(rco-|r-brdr).*>" *.html
… sybase-iq-12.7-migration-ase-vers-iq.html:53: <table class="alt- r-brdr rco-"> sybase-iq-12.7-migration-ase-vers-iq.html:121: <table class="alt- r-brdr rco-"> sybase-iq-12.7-migration-ase-vers-iq.html:152: <table class="alt- r-brdr rco-"> sybase-iq-12.7-migration-ase-vers-iq.html:232: <table class="alt- r-brdr rco-"> sybase-iq-12.7-migration-ase-vers-iq.html:661: <table class="alt- r-brdr"> …
Lister les fichiers *.html
ne contenant pas de tableaux (option -L
) :
grep -L "<table" *.html