Comment combiner recherche et grep pour une recherche complexe? (GNU / linux, trouver, grep)

17

J'essaie de faire une recherche de texte dans certains fichiers qui partagent une structure de répertoires similaire, mais qui ne sont pas dans la même arborescence de répertoires, sous GNU / Linux.

J'ai un serveur web avec de nombreux sites qui partagent la même arborescence (framework PHP Code Igniter MVC), donc je veux rechercher dans un répertoire spécifique dans l'arborescence de chaque site, par exemple:

/srv/www/*/htdocs/system/application/

Où * est le nom du site. Et à partir de ces répertoires d' application , je veux rechercher dans tout l'arborescence jusqu'à ses feuilles, un fichier * .php qui contient un modèle de texte, disons "debug (", aucune expression régulière nécessaire.

Je sais utiliser find et grep mais je ne suis pas bon pour les combiner.

Comment pourrais-je faire ça?
Merci d'avance!

Petruza
la source

Réponses:

21

Essayer

find /srv/www/*/htdocs/system/application/ -name "*.php" -exec grep "debug (" {} \; -print

Cela devrait récursivement rechercher dans les dossiers sous les applicationfichiers avec .phpextension et les transmettre à grep.

Une optimisation à ce sujet serait d'exécuter:

find /srv/www/*/htdocs/system/application/ -name "*.php" -print0 | xargs -0 grep -H "debug ("

Cela permet xargsde passer tous les .phpfichiers produits en findtant qu'arguments à une seule grepcommande; par exemple . L' option et l' option de garantir que les espaces dans les noms de fichiers et de répertoires sont correctement gérés. L' option passée à garantit que le nom de fichier est imprimé dans toutes les situations. (Par défaut, imprime le nom de fichier uniquement lorsque plusieurs arguments sont transmis.)grep "debug (" file1 file2 file3-print0find-0xargs-Hgrepgrep

De l'homme xargs:

-0

      Les éléments d'entrée se terminent par un caractère nul au lieu de par des espaces, et les guillemets et les barres obliques inverses ne sont pas spéciaux (chaque caractère est pris littéralement). Désactive la fin de la chaîne de fichiers, qui est traitée comme tout autre argument. Utile lorsque les éléments d'entrée peuvent contenir des espaces blancs, des guillemets ou des barres obliques inverses. L' -print0option GNU find produit une entrée adaptée à ce mode.

nagul
la source
1
+1. Cela exécutera cependant grep pour chaque fichier php. S'il y a beaucoup de fichiers, vous pouvez optimiser davantage parfind /srv/www/*/htdocs/system/application/ -name "*.php" -print0 | xargs -0 grep "debug ("
Jukka Matilainen
@jackem d'accord. Je mettrai à jour ma réponse en conséquence.
nagul
2
Autre petite amélioration: xargs peut simplement passer un nom de fichier à grep, auquel cas grep n'affichera pas le nom de fichier s'il y a une correspondance. Vous voudrez peut-être ajouter -H à la commande grep pour la forcer à afficher le nom de fichier.
Randy Orrison le
@Randy C'est un point très valable.
nagul le
3
C'est de la nécromancie vraie, mais cela GNU findpeut prendre l' +opérateur au lieu d' \;effectuer le même type d'exécution de processus unique que le xargsfont. Ainsi, find /srv/www/*/htdocs/system/application/ -name "*.php" -exec grep -H "debug (" {} +fait la même chose que l' xargsexemple dans cette réponse, mais avec un fork de processus en moins (et toujours 0 risque de problèmes de nom de fichier).
Daniel Andersson
10

findn'est même pas nécessaire pour cet exemple, on peut utiliser grepdirectement (au moins GNU grep):

grep -RH --include='*.php' "debug (" /srv/www/*/htdocs/system/application/

et nous en sommes à une seule fourche de processus.

Options:

  • -R, --dereference-recursive Read all files under each directory, recursively. Follow all symbolic links, unlike -r.
  • -H, --with-filename Print the file name for each match. This is the default when there is more than one file to search.
  • --include=GLOB Search only files whose base name matches GLOB (using wildcard matching as described under --exclude).
  • --exclude=GLOB Skip any command-line file with a name suffix that matches the pattern GLOB, using wildcard matching; a name suffix is either the whole name, or any suffix starting after a / and before a +non-/. When searching recursively, skip any subfile whose base name matches GLOB; the base name is the part after the last /. A pattern can use *, ?, and [...] as wildcards, and \ to quote a wildcard or backslash character literally.
Daniel Andersson
la source
Juste pour la curiosité, que -RHsignifient les options?
Gus
@Gus: Ajout d'un man grepextrait des descriptions des options au message.
Daniel Andersson
0

Votre shell peut trouver les fichiers php et les donner à grep. En bash:

shopt -s nullglob globstar
grep searchterm /srv/www/*/htdocs/system/application/**/*.php
user2394284
la source