Gibt es eine einfachere Möglichkeit, alle Dateien in einem Verzeichnis zu durchsuchen?

21

Wenn ich einen ganzen Baum nach Inhalten durchsuchen möchte, verwende ich

find . -type f -print0 | xargs -0 grep <search_string>

Gibt es einen besseren Weg, dies in Bezug auf Leistung oder Kürze zu tun?

Dancrumb
quelle
2
@ Downvoter: Freut mich, diese Frage zu verbessern, wenn Sie Ihre Bedenken teilen können.
Dancrumb
2
in vielen find-versionen sind xargs eingebaut: find. -type f -exec fgrep <Suchzeichenfolge> {} +
simpleuser

Antworten:

42

Überprüfen Sie, ob Ihre grepUnterstützungsoption -r(für den Rückgriff ):

grep -r <search_string> .
Philippos
quelle
1
Yup ... Ich habe gerade stackoverflow.com/questions/16956810/… gefunden und das ist auch die Antwort.
Dancrumb
Fügen Sie einen Kommentar hinzu --exclude-dir, um die Leistung zu adressieren und wir haben einen Gewinner!
Dancrumb
1
grepBeachten Sie nur, dass dies nicht portabel ist, jedoch von den neuesten FreeBSD- und Linux-Distributionen unterstützt wird. Und warum --exclude-dir? Haben Sie nicht darum gebeten, einen ganzen Baum zu durchsuchen ?
Philippos
Richtiger Punkt ... --exclude-dirist in meinem Anwendungsfall praktisch (da Teile des Teilbaums groß, aber nutzlos sind) und ich habe nach der Leistung gefragt ... aber Sie haben Recht, das ist nicht erforderlich.
Dancrumb
In diesem Fall muss ich hinzufügen, dass IIRC --exclude-direxklusiv für GNU ist grep. (-:
Philippos
13

Eine suboptimale Antwort: Anstatt die Ausgabe von findin zu grepleiten, könnten Sie einfach laufen

find . -type f -exec grep 'research' {} '+'

und voila, ein befehl statt zwei!

Erklärung:

find . -type f

Finden Sie alle regulären Dateien in.

-exec grep 'research'

grep "Forschung"

{}

im gefundenen Dateinamen

'+'

Verwenden Sie einen Befehl pro Dateiname und nicht ein Mal pro Dateiname.

Nb: ';'damit wäre einmal pro Dateiname gewesen.

Wenn Sie das zum Verarbeiten von Quellcode verwenden, können Sie nachsehen ack, wo Sie auf einfache Weise nach Codebits suchen können.

ack

Bearbeiten:

Sie können diese Forschung ein wenig erweitern. Erstens können Sie den -name ''Schalter von verwenden find, um nach Dateien mit einem bestimmten Benennungsmuster zu suchen.

Zum Beispiel :

  • Nur Dateien, die Protokollen entsprechen: -name '*.log'

  • Nur Dateien, die c-Headern entsprechen, bei den Dateinamenerweiterungen können Sie jedoch weder Groß- noch Kleinbuchstaben verwenden: -iname *.c

Anmerkung: Wie für grepund bedeutet ackder -iSchalter in diesem Fall , dass die Groß- und Kleinschreibung nicht beachtet wird.

In diesem Fall wird grep ohne Farbe und ohne Zeilennummern angezeigt.

Sie können , dass mit der Änderung --colorund die -nSchalter (Farbe und Linien Nummern in Dateien respectively).

Am Ende können Sie etwas haben wie:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'

zum Beispiel

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello
Pierre-Antoine Guillaume
quelle
5
ackist großartig, und eine schnellere Version von ackis ag(the silver searcher , geoff.greer.fm/ag )
cfeduke 16.08.17
1
Ich bevorzuge dies mit Filter wie -name '*.log'Es ist schneller.
SDKKS
@cfeduke Ich habe es nicht ausprobiert, vor allem, weil ag nicht Teil der Standard-Repositorys für WSL ist (du musst mit dem arbeiten, was du hast!)
Pierre-Antoine Guillaume
Ein Trick besteht darin, / dev / null zum grep hinzuzufügen, damit der Dateiname angezeigt wird.
ChuckCottrill
Ein Trick besteht darin, nur nach Verzeichnissen zu suchen und dann -exec grep / dev / null {} / *, um alle Dateien mit einem Fork / Exec pro Verzeichnis abzurufen.
ChuckCottrill
12

Wenn Sie in Unterverzeichnisse zurückkehren möchten:

grep -R 'pattern' .

Die -ROption ist keine Standardoption, wird jedoch von den meisten gängigen grepImplementierungen unterstützt.

Kusalananda
quelle
7
Verwenden Sie -rstatt -Rüberspringen Symlinks , wenn GNU grep betroffen ist
αғsнιη
1
@AFSHIN Warum möchten Sie Symlinks nicht folgen?
Kusalananda
4
@Kusalananda Rekursion? Obwohl aktuelle GNU- grepImplementierungen Rekursionen verursachen, denke ich. Ansonsten kommt es darauf an, was du mit "Baum" meinst.
Philippos
2
@Philippos IMHO, Babysitten für den Benutzer ist nichts, was ein Tool wie greptun sollte. Wenn der Benutzer symbolische Linkschleifen in seiner Verzeichnisstruktur hat, ist das das Problem des Benutzers :-)
Kusalananda
3
@Kusalananda Und wenn das System die Schleife zur Verfügung gestellt? Ich habe /sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...mich nie verlaufen in (-XI mag Werkzeuge, die mich babysitten (es sei denn, sie bieten seltsame Magie, die sie "KI" nennen). (-;
Philippos
5

Wie oben erwähnt -roder -R(abhängig vom gewünschten Symlink-Handling) ist eine schnelle Option.

Jedoch -d <action>kann manchmal nützlich sein.

Das Schöne daran -dist der Befehl skip, der das "grep: directory_name: Is a directory" zum Schweigen bringt, wenn Sie nur die aktuelle Ebene durchsuchen möchten.

$ grep foo * 
grep: q2: Is a directory 
grep: rt: Is a directory 

$ grep -d skip foo *  
$ 

und natürlich:

$ grep -d recurse foo * 
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).  
$ 

Die -d skipOption ist in einem anderen Skript WIRKLICH praktisch, sodass Sie sie nicht benötigen 2> /dev/null. :)

Petro
quelle
0

Wenn Sie mit vielen Dateien arbeiten, wird das grep schneller ausgeführt, wenn Sie die zu durchsuchenden Dateien zurückschneiden, anstatt alle Dateien in Unterordnern zu durchsuchen.

Ich benutze manchmal dieses Format:

grep "primary" `find . | grep cpp$`

Alle Dateien in Unterordner von .diesem Ziel cpp. Dann grep diese Dateien für "primäre".

Wenn Sie möchten, können Sie diese Ergebnisse in weitere grep-Aufrufe umleiten:

grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"
Rudy
quelle
1
Backtics sind keine gute moderne Praxis, sie sind alles andere als veraltet
Christopher
1
Dies wird unterbrochen, wenn Sie Dateien mit Sonderzeichen im Namen haben. Ich weiß nicht, wie speziell sie sein müssen, um zu speziell zu sein, damit dies so funktioniert, wie es ist, aber was Sie tun, ist im Grunde dasselbe wie das Parsen der Ausgabe von ls, was ebenfalls schlecht ist.
ein Lebenslauf vom