Wie kombiniere find und grep für eine komplexe Suche? (GNU / linux, find, grep)

21619
Petruza

Ich versuche eine Textsuche in einigen Dateien durchzuführen, die eine ähnliche Verzeichnisstruktur haben, sich aber nicht in derselben Verzeichnisstruktur in GNU / Linux befinden.

Ich habe einen Webserver mit vielen Sites, die dieselbe Baumstruktur verwenden (Code Igniter MVC PHP-Framework). Daher möchte ich in einem bestimmten Verzeichnis in der Baumstruktur nach jeder Site suchen. Beispiel:

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

Wo * ist der Site-Name. Und aus diesen Anwendungsverzeichnissen möchte ich den gesamten Baum bis zu seinen Blättern durchsuchen. Nach einer * .php-Datei, die Textmuster enthält, sagen wir "debug" (kein regulärer Ausdruck erforderlich).

Ich weiß, wie man find und grep benutzt, aber ich kann sie nicht gut kombinieren.

Wie würde ich das machen?
Danke im Voraus!

15

3 Antworten auf die Frage

18
nagul

Try

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

This should recursively search the folders under application for files with .php extension and pass them to grep.

An optimization on this would be to execute:

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

This uses xargs to pass all the .php files output by find as arguments to a single grep command; e.g., grep "debug (" file1 file2 file3. The -print0 option of find and -0 option of xargs ensure the spaces in file and directory names are correctly handled. The -H option passed to grep ensures that the filename is printed in all situations. (By default, grep prints the filename only when multiple arguments are passed in.)

From man xargs:

-0

      Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally).  Disables the end of file string, which is treated like any other argument.  Useful when input items might contain white space, quote marks, or backslashes.  The GNU find -print0 option produces input suitable for this mode.

+1. Das wird allerdings für jede PHP-Datei grep ausführen. Wenn es viele Dateien gibt, können Sie mit `find / srv / www / * / htdocs / system / application / -name" * .php "-print0 | weiter optimieren xargs -0 grep "debug (" ` Jukka Matilainen vor 14 Jahren 1
@jackem vereinbart Ich werde meine Antwort entsprechend aktualisieren. nagul vor 14 Jahren 0
Eine weitere kleine Verbesserung: xargs kann nur einen Dateinamen an grep übergeben. In diesem Fall zeigt grep den Dateinamen nicht an, wenn eine Übereinstimmung vorliegt. Sie können -H zum Befehl grep hinzufügen, um den Dateinamen anzuzeigen. Randy Orrison vor 14 Jahren 2
@ Randy Das ist ein sehr gültiger Punkt. nagul vor 14 Jahren 0
Dies ist zwar eine Nekromantie, aber für "GNU find" kann der Operator "+" anstelle von "\" verwendet werden, um dieselbe Art der Ausführung eines einzelnen Prozesses wie "xargs" auszuführen. `Find / srv / www / * / htdocs / system / application / -name" * .php "-exec grep -H" debug ("{} +" führt dasselbe aus wie das `xargs`-Beispiel in dieser Antwort , aber mit einer Prozessgabel weniger (und immer noch kein Risiko für Dateinamenprobleme). Daniel Andersson vor 12 Jahren 3
9
Daniel Andersson

find is not even needed for this example, one can use grep directly (at least GNU grep):

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

and we are down to a single process fork.

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.
Nur aus Neugier, was bedeuten die "-RH" -Optionen? Gus vor 7 Jahren 0
@Gus: "man grep" Auszug der Optionsbeschreibungen zum Beitrag hinzugefügt. Daniel Andersson vor 7 Jahren 0
0
user2394284

Ihre Shell kann die PHP-Dateien finden und sie an grep übergeben. In Bash:

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