rekursives grep: bestimmte Verzeichnisse ausschließen

49

Ich verwende häufig rekursives grep, um Quelldateien mit bestimmten Inhalten zu finden.

grep -Rni "myfunc" .

Bei großen Codebasen kann dies langsam werden. Daher verwende ich --incldue, um Erweiterungen / Whitelists einzuschränken.

grep -Rni --include=*.java "myfunc" .

Es wäre jedoch effizienter, ganze Unterverzeichnisse auszuschließen (zu beschneiden), denke ich:

grep -Rni --exclude=/.svn/ "myfunc" .

Aber das --exclude unterstützt nur Dateimuster wie * .java. Wie kann ich Verzeichnisse ausschließen?

Gabor
quelle

Antworten:

10

Sie könnten in ack schauen .

Ich habe gerade damit begonnen, aber es scheint gut dafür geeignet zu sein.

Alex Feinman
quelle
ack sieht ziemlich gut aus. schön, dass es intuitiv unerwünschte Dateien ausschließt. die --nogroup Option gibt eine ähnliche Ausgabe -Rni grep
gabor
2
Ack ist etwas langsam. Sie können The Silver Searcher (Ag) oder ripgrep (rg) ausprobieren.
user31389
62
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Quelle: https://stackoverflow.com/questions/2799246/grep-excluding-a-specific-folder-using

Henrik
quelle
17
Beachten Sie, dass dies rekursiv ausschließt. ./devwird MIT AUSGESCHLOSSEN ./foo/bar/dev. Verwenden Sie --exclude-dir=./devdiese Option nur für den ersten Fall.
Cory Walker
4
Sie können dies auch ein wenig durch Globbing verkürzen: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data Das einzige Problem beim Globbing ist, dass ich es in meiner Bash nicht zum Laufen bringen kann. In diesem Fall muss ich sie getrennt halten.
b01
3
Beachten Sie auch, dass {} nur funktioniert, wenn Sie mehr als 1 Einträge eingeben. Dies bedeutet, dass --exclude-dir = {home, .svn} funktioniert, --exclude-dir = {. Svn} jedoch nicht. Es verschwendet meine Zeit, herauszufinden, warum {} nicht funktioniert, da ich zunächst mit 1 Eintrag teste.
林果 皞
Wenn Sie {}einen einzelnen Eintrag verwenden, benötigen Sie wahrscheinlich ein unäres Komma, um ein Array zu erstellen (nicht sicher, wie Bash damit umgeht). Stattdessen habe ich in meinen .bash_aliases einen Alias ​​erstellt, der eine Liste von Ordnern durchläuft, die ich normalerweise immer ausschließen möchte, z. B. .git, .svn, .hg, .cache. Anschließend füge ich sie über eine Schleife mit hinzu --exclude-dir $dirund erweitern Sie dann dieses Array in den Grep-Alias.
Dragon788
6

Sie können stattdessen find verwenden:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

OK, das ist ein bisschen rückwärts, Sie erhalten zuerst die grep-Ergebnisse und dann den Pfad. Vielleicht hat jemand anderes eine bessere Antwort?

Josh
quelle
3
ok, das gefällt mir sehr gut find ist natürlich wesentlich flexibler. Der einzige Unterschied zwischen der Ausgabe besteht darin, dass "grep -Rni" den Dateinamen für jede Übereinstimmung ausgibt, während "find -exec grep" den Dateinamen in einer Zeile und dann in einer Zeile für jede Übereinstimmung (mit Zeilennummer und Zeileninhalt) ausgibt ). mit "grep -Hni" wird der Dateiname in jeder Zeile angezeigt
gabor
Vielen Dank, dass Sie die einzige Antwort geliefert haben, die für Systeme funktioniert hat, die so knusprig sind, ohne grep --exclude-dir, an der aber noch gearbeitet werden muss
Dmitri DB,
2

Hier ist ein vollständiges Beispiel eines Skripts in einem meiner Projekte, das möglicherweise hilfreich ist. Ich bezeichne diese Datei als "all_source" (als ausführbar markiert) und füge sie in das Stammverzeichnis meines Projekts ein. Nenne sie dann so, wie es grep myfunc $(./all_source)die Sortierung am Ende des Skripts ist Optional.

#!/bin/bash

find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

Dieses Skript gibt alle Dateinamen im Projekt zurück, die übereinstimmen *.h, *.cpp, *.c, *.lua, *.*awk, durchsucht jedoch nicht alle Ordner mit den Namen .svn und gen und überspringt die Ordner nach ./libund ./vc6(sondern nur diejenigen, die sich direkt hinter dem Projektstamm befinden). Wenn Sie dies tun grep myfunc $(./all_source), greift dies nur in diesen Dateien. Sie müssen dies auch aus dem Stammverzeichnis des Projekts aufrufen.

Mike Nelson
quelle
0

Es gibt auch die Option -prune, um Folgendes zu finden:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
misiu_mp
quelle
0

Sie können dies versuchen:

grep -R  "myfunc" . | grep -v path_to_exclude/

Beispiel: Wenn Sie den Inhalt in Protokolldateien nicht durchsuchen möchten, gehen Sie wie folgt vor:

grep -R "myfunc" . | grep -v log/
Akshatha
quelle