Wie kann ich Verzeichnisse von grep -R ausschließen?

667

Ich möchte alle Unterverzeichnisse mit Ausnahme des Verzeichnisses "node_modules" durchlaufen.

TIMEX
quelle
3
Siehe superuser.com/q/66715/59933
borrible
14
Geben Sie einfach "man grep" ein und Sie werden sehen, dass die Optionen --exclude und --exclude-dir genau dort aufgelistet sind. Aus der Überschrift dieser Frage
gehe
34
Wenn Sie in einem Git-Repository nach Code suchen und node_modulessich in Ihrem befinden .gitignore, git grep "STUFF"ist dies der einfachste Weg. git grepdurchsucht die verfolgten Dateien im Arbeitsbaum und ignoriert alles von.gitignore
0xcaff
2
Ein Beispiel für einen Knoten: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- Außerdem können Sie dies in der Shell immer als 'nodegrep' oder was auch immer aliasen und ein Befehlsargument als Zeichenfolgeneingabe verwenden.
bshea

Antworten:

394

LÖSUNG 1 (kombinieren findund grep)

Der Zweck dieser Lösung ist nicht zu behandeln grep Leistung sondern eine tragbare Lösung zu zeigen: Sollte auch mit einer Busybox- oder GNU-Version funktionieren, die älter als 2.5 ist.

Verwenden Sie findzum Ausschließen von Verzeichnissen foo und bar:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Dann kombinieren findund die nicht rekursive Verwendung grepals tragbare Lösung:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

LÖSUNG 2 (rekursive Verwendung von grep):

Sie kennen diese Lösung bereits, aber ich füge sie hinzu, da sie die neueste und effizienteste Lösung ist. Beachten Sie, dass dies eine weniger tragbare Lösung ist, die jedoch besser lesbar ist.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Verwenden Sie Folgendes, um mehrere Verzeichnisse auszuschließen --exclude-dir:

--exclude-dir={node_modules,dir1,dir2,dir3}

LÖSUNG 3 (Ag)

Wenn Sie häufig nach Code suchen, ist Ag (The Silver Searcher) eine viel schnellere Alternative zu grep, die für die Suche nach Code angepasst ist. Beispielsweise werden die darin aufgeführten Dateien und Verzeichnisse automatisch ignoriert .gitignore, sodass Sie nicht immer dieselben umständlichen Ausschlussoptionen an grepoder übergeben müssen find.

hornetbzz
quelle
2
Diese Kombination sucht schneller als --exclude-dir=dirund zeigt Ergebnisse mit Farben - leicht zu lesen
Maxim Yefremov
27
"diese Kombination" find ... -execist nicht schneller als grep --exclude-dirfür mich. Sehr großer Vorteil grep (etwa fünfmal schneller mit 26k + Dateien, von 38k + auf einem HDD herausgefiltert), es sei denn , Sie ersetzen die \;mit +für die find / exec - Combo. Dann ist grep "nur" etwa 30% schneller. Die grep-Syntax ist auch für Menschen lesbar :).
Kjell Andreassen
Einverstanden, da dies offensichtlich ist. Einige Busyboxen verfügen nicht über den Befehl GREP.
Hornetbzz
10
Beachten Sie auch, dass Sie mehrere mit--exclude-dir={dir1,dir2}
suh
4
Ich bin nicht im geringsten überrascht, dass dies node_modulesdas kanonische Beispiel ist.
pdoherty926
981

Aktuelle Versionen von GNU Grep (> = 2.5.2 ) bieten:

--exclude-dir=dir

Dies schließt Verzeichnisse, die dem Muster entsprechen, dirvon rekursiven Verzeichnissuchen aus.

So können Sie tun:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Weitere Informationen zu Syntax und Verwendung finden Sie unter

Für ältere GNU Greps und POSIX Grep , Verwendung findwie in anderen Antworten vorgeschlagen.

Oder verwenden Sie einfach ack( Edit : oder The Silver Searcher ) und fertig!

Johnsyweb
quelle
4
@ Manocho: Wenn Sie der Meinung acksind, dass es großartig ist, probieren Sie The Silver Searcher aus und sehen Sie, wie die Geschwindigkeit steigt!
Johnsyweb
30
Syntax für Ungeduldige: --exclude-dir=dirVerwendet grepdie regulären Ausdrucksmuster, nicht das Globbing von Shell-Dateien. Muster arbeiten mit Pfaden relativ zu Ihrem aktuellen Verzeichnis. Verwenden Sie also --exclude-dir=dirkein Muster --exclude-dir="/root/dir/*".
Tanius
15
Wenn Sie mehrere Verzeichnisse von der Suche ausschließen möchten, gibt es eine bessere Möglichkeit , als zu verwenden: $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir?
Darshan Chaudhary
4
Ich habe wahrscheinlich viel zu viel Zeit damit verbracht als jede vernünftige Person, aber ich kann für mein ganzes Leben nicht herausfinden, wie ich ein Unterverzeichnis von der Suche ausschließen kann - grep -r --exclude-dir=public keyword .funktioniert, aber grep -r --exclude-dir='public/dist' keyword .nicht. Ich habe versucht, Regex-Platzhalter hinzuzufügen, Zeichen zu entkommen usw., aber nichts scheint zu helfen.
dkobozev
72
Schließen Sie mehrere Verzeichnisse wie folgt aus:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97
77

Wenn Sie mehrere Verzeichnisse ausschließen möchten :

"r" für rekursiv, "l", um nur Namen von Dateien zu drucken, die Übereinstimmungen enthalten, und "i", um Fallunterscheidungen zu ignorieren:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Beispiel: Ich möchte Dateien finden, die das Wort "Hallo" enthalten. Ich möchte in allen meinen Linux-Verzeichnissen suchen, außer im Proc- Verzeichnis, im Boot- Verzeichnis, im Sys- Verzeichnis und im Root- Verzeichnis:

grep -rli --exclude-dir={proc,boot,root,sys} hello /

Hinweis: Das obige Beispiel muss root sein

Hinweis 2 (laut @skplunkerin): Fügen Sie nach den Kommas in keine Leerzeichen ein {dir1,dir2,dir3}

Azodium
quelle
5
HINWEIS:{dir1,dir2,dir3}
Fügen
Vielen Dank, praktisch beim Durchsuchen des SVN-Arbeitsbereichs:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237
1
Sie können die --exclude-dirOption einfach mehrmals angeben.
Walf
44

Diese Syntax

--exclude-dir={dir1,dir2}

wird durch die Shell (zB Bash) erweitert, nicht durch grep, in diese:

--exclude-dir=dir1 --exclude-dir=dir2

Das Zitieren verhindert, dass die Shell sie erweitert, sodass dies nicht funktioniert:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Bei den verwendeten Mustern handelt es --exclude-dirsich um die gleichen Muster, die in der Manpage für die --excludeOption beschrieben wurden:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

Die Shell versucht im Allgemeinen , ein solches Muster selbst zu erweitern. Um dies zu vermeiden, sollten Sie es zitieren:

--exclude-dir='dir?'

Sie können die geschweiften Klammern und die zitierten Ausschlussmuster wie folgt zusammen verwenden:

--exclude-dir={'dir?','dir??'}

Ein Muster kann mehrere Pfadsegmente umfassen:

--exclude-dir='some*/?lse'

Dies würde ein Verzeichnis wie ausschließen topdir/something/else.

Derek Veit
quelle
13

Verwenden Sie dies häufig:

grepkann in Verbindung mit -r(rekursiv), i(Groß- / Kleinschreibung ignorieren) und -o(druckt nur übereinstimmende Teile von Zeilen) verwendet werden. filesVerwendung ausschließen --excludeund Verwendung von Verzeichnissen ausschließen --exclude-dir.

Wenn Sie es zusammensetzen, erhalten Sie Folgendes:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

Wenn man es beschreibt, klingt es weitaus komplizierter als es tatsächlich ist. Einfacher mit einem einfachen Beispiel zu veranschaulichen.

Beispiel:

Angenommen, ich suche nach dem aktuellen Projekt für alle Stellen, an denen ich den Zeichenfolgenwert debuggerwährend einer Debugging-Sitzung explizit festgelegt habe , und möchte nun überprüfen / entfernen.

Ich schreibe ein Skript namens findDebugger.shund benutze es grep, um alle Vorkommen zu finden. Jedoch:

Für Dateiausschlüsse - Ich möchte sicherstellen, dass dies .eslintrcignoriert wird (dies hat tatsächlich eine Flusenregel, debuggerdie ausgeschlossen werden sollte). Ebenso möchte ich nicht, dass in einem Ergebnis auf mein eigenes Skript verwiesen wird.

Für Verzeichnisausschlüsse - Ich möchte ausschließen, node_modulesda es viele Bibliotheken enthält, auf die verwiesen wird, debuggerund ich bin nicht an diesen Ergebnissen interessiert. Außerdem möchte ich nur Verzeichnisse weglassen .ideaund .gitausblenden, weil mir diese Suchorte auch egal sind, und ich möchte die Suche performant halten.

Hier ist das Ergebnis: Ich erstelle ein Skript mit dem Namen findDebugger.sh:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
arcseldon
quelle
Ich glaube, die Option "r" sollte mit einem Großbuchstaben "-R" gedruckt werden.
Hornetbzz
1
Interessant. "r" hat immer für mich auf nix und mac funktioniert.
Arcseldon
Als ich meine Antwort schrieb , benutzte -Rich (ich erinnere mich nicht, warum jetzt). Ich benutze normalerweise -r. Es stellt sich heraus, dass die Version in Großbuchstaben Symlinks folgt . Bis.
Johnsyweb
@ Johnsyweb - danke. Ihre Antwort wurde positiv bewertet - ich erinnere mich nicht, wann, wahrscheinlich im Jahr 2016, als ich diese hinzugefügt habe :)
arcseldon
10

Sie könnten so etwas versuchen grep -R search . | grep -v '^node_modules/.*'

DIP Schalter
quelle
34
In einigen Fällen keine so gute Lösung. Beispiel: Wenn das Verzeichnis 'node_modules' sehr umfangreich ist und viele falsch positive Übereinstimmungen aufweist (daher muss das Verzeichnis herausgefiltert werden), verschwendet der erste grep viel Zeit beim Durchsuchen eines Unterverzeichnisses und DANN beim zweiten grep-Filtern aus den Streichhölzern. Es ist schneller, node_modules im ersten grep selbst auszuschließen.
GuruM
2
Die Langsamkeit ist mir egal, ich kann mir den Befehl ansehen und wissen, was er tut
Funkodebat
1
Das Gleiche gilt für Gurus Kommentar. Ein Grep /varhängt, wenn es /var/runin meinem Fall trifft . Daher möchte ich das Verzeichnis überhaupt vermeiden.
JWW
3
--exclude-dirist die beste Lösung ab 2016.
Omar Tariq
10

Wenn Sie in einem Git-Repository nach Code suchen und node_modulessich in Ihrem befinden .gitignore, können Sie verwenden git grep. git grepDurchsucht die verfolgten Dateien im Arbeitsbaum und ignoriert alles von.gitignore

git grep "STUFF"
0xcaff
quelle
Dies ist ein sehr nützlicher Tipp. Danke.
NKM
4

Sehr nützlich, insbesondere für diejenigen, die sich mit Node.js beschäftigen und die Suche in "node_modules" vermeiden möchten:

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
Nestor Urquiza
quelle
2

Ein einfacher Arbeitsbefehl:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Oben suche ich im aktuellen Verzeichnis "dspace" nach dem Text "creativecommons.org" und schließe dirs {log, assetstore} aus.

Erledigt.

Dung
quelle
Ordentlich, einschließlich mehrerer Verzeichnisse in Klammern
Mijo
2

Hier wurden viele richtige Antworten gegeben, aber ich füge diese hinzu, um einen Punkt hervorzuheben, der dazu geführt hat, dass einige überstürzte Versuche zuvor fehlgeschlagen sind: exclude-dirNimmt ein Muster , keinen Pfad zu einem Verzeichnis.

Angenommen, Ihre Suche lautet:

grep -r myobject

Und Sie bemerken, dass Ihre Ausgabe mit Ergebnissen aus dem überladen ist src/other/objects-folder. Dieser Befehl wird nicht geben Sie das gewünschte Ergebnis:

grep -r myobject --exclude-dir=src/other/objects-folder

Und Sie fragen sich vielleicht, warum exclude-dirdas nicht funktioniert! Um die Ergebnisse tatsächlich von der auszuschließen objects-folder, gehen Sie einfach wie folgt vor :

grep -r myobject --exclude-dir=objects-folder

Mit anderen Worten, verwenden Sie einfach den Ordnernamen und nicht den Pfad. Offensichtlich, sobald Sie es wissen.

Von der Manpage:

--exclude-dir = GLOB
Überspringt jedes Befehlszeilenverzeichnis mit einem Namenssuffix, das dem Muster GLOB entspricht. Überspringen Sie bei der rekursiven Suche jedes Unterverzeichnis, dessen Basisname mit GLOB übereinstimmt. Ignorieren Sie redundante nachgestellte Schrägstriche in GLOB.

Nagev
quelle
2

Dieser funktioniert für mich:

grep <stuff> -R --exclude-dir=<your_dir>
angelo.mastro
quelle
5
Wie unterscheidet sich diese Antwort von der bereits veröffentlichten?
Aexl
1
find . ! -name "node_modules" -type d 
Jack
quelle
-1

Eine einfachere Möglichkeit wäre, Ihre Ergebnisse mit "grep -v" zu filtern.

grep -i needle -R * | grep -v node_modules

Morris
quelle
12
Dies ist praktisch die gleiche Antwort, die DipSwitch 3 Jahre zuvor gegeben hat. Es hat auch die gleichen Probleme.
JWW