Suchen eines Teilstrings in Dateien über Unterverzeichnisse hinweg mit einem einzigen integrierten Befehl?

10

Wenn ich in Windows eine Zeichenfolge für alle Dateien in allen Unterverzeichnissen finden wollte, würde ich so etwas tun

findstr /C:"the string" /S *.h

Unter Linux (z. B. Ubuntu) habe ich jedoch keinen anderen Weg gefunden als einen Pipeline-Befehl mit find, xargsund grep(ein Beispiel finden Sie auf dieser Seite: Wie kann ich rekursiv durch Unterverzeichnisse blättern? ). Meine Frage ist jedoch anders: Gibt es einen einzelnen integrierten Befehl , der diese Magie verarbeitet, ohne mein Shell-Skript schreiben zu müssen?

Guido Domenici
quelle

Antworten:

19

GNU grep ermöglicht die rekursive Suche in Unterverzeichnissen:

grep -r --include='*.h' 'the string' .
wedeln
quelle
Ich habe genau diese Befehlszeile in Ubuntu ausprobiert, aber "grep: ungültige Option - 'M'" erhalten, obwohl ich nirgendwo ein 'M' sehen kann ... rätselhaft
Guido Domenici
@ Guido Funktioniert gut hier
Phunehehe
In einer vorgeschlagenen Änderung empfiehlt TomasG , den letzten *in Folgendes zu ändern '*': "Das Zitieren des letzten Platzhalters ist erforderlich, um Fehler zu vermeiden, wenn ein Dateiname mit - beginnt"
Michael Mrozek
In einer seltsamen Wendung von Ereignissen funktioniert es jetzt auch für mich, wie in der ursprünglichen Antwort eingegeben. Vielen Dank!
Guido Domenici
1
@Guido: Möglicherweise liegt Ihr Problem an einer Datei im aktuellen Verzeichnis -Msomethingoder an einer GREP_OPTIONSEinstellung.
Gilles 'SO - hör auf böse zu sein'
2

grep -r searchpattern /path/to/start/in

Wo /path/to/start/in/kann nur " ." für das aktuelle Verzeichnis sein.

mattdm
quelle
1

Nein find -name \*.h -print0 | xargs -0 grep -l 'the regex'ist so magisch wie es nur geht.

Glenn Jackman
quelle
In GNU grep sind die gängigen Fälle mit seiner -rOption integriert. Keine Notwendigkeit für die schwere Artillerie.
Gilles 'SO - hör auf böse zu sein'
3
xargsfügt nur Lärm hinzu. Verwendungfind -name \*.h -execdir grep -l 'the regex {} +
Benutzer unbekannt
0

Gibt es einen einzigen eingebauten Befehl , der durch diese Magie funktioniert ...?

Um pedantisch zu sein, nein, Sie können nicht davon ausgehen, dass ein solcher Befehl existiert .

Es gibt viele verschiedene Implementierungen von Unix, und jede hat ihre eigenen Macken. POSIX, der gemeinsame Nenner (und einem Standard in allen Einheiten am nächsten), gibt eine solche Option für nicht angrep .

Wie in anderen Antworten erwähnt, verfügt die Implementierung von GNU grepüber eine nicht standardmäßige Option, die das tut, was Sie wollen. Während diese spezielle Implementierung auf Linux-Systemen häufig vorkommt, können Sie nicht davon ausgehen, dass sie unter Unix verfügbar ist, auch nicht auf einigen Linux-Systemen.

Abschließend sollte ich erwähnen, dass es die Unix-Philosophie ist , die Kombination mehrerer primitiver Programme gegenüber der Verwendung einer großen monolithischen ausführbaren Datei zu bevorzugen, die versucht, alles auf einmal zu tun.

In Ihrem Fall sind das Crawlen des Dateisystems und das Abgleichen des regulären Ausdrucks in einem Stream zwei separate Aufgaben. Es ist nur normal, jedes in einem separaten Programm zu behandeln.

Rahmu
quelle
0

Verwenden Sie den folgenden Befehl, um eine Zeichenfolge aus einem bestimmten Verzeichnis zu finden

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

Beispielsweise:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;
Yogesh
quelle
1
grepkann mehr als eine Datei als Argumente verwenden, daher sollten Sie +stattdessen verwenden \;, um zu vermeiden, dass ein grepAufruf pro Datei ausgeführt wird, was ziemlich ineffizient ist.
Stéphane Chazelas
1
Beachten Sie, dass dies -name '*'auf Dateien beschränkt ist, deren Name im aktuellen Gebietsschema gültiger Text ist ( findzumindest in einigen Implementierungen), die anderen Verzeichniskomponenten jedoch möglicherweise weiterhin Folgen von Bytes enthalten, die keine gültigen Zeichen bilden. Wenn Sie -name '*'damit sicherstellen möchten, dass die Ausgabe gültiger Text ist (indem Sie die Dateien mit falschen Namen weglassen), find ... ! -name '*' -prune -o -exec grep ... {} +möchten Sie lieber verwenden , was auch verhindern würde , dass Sie findin Verzeichnisse mit falschen Namen absteigen.
Stéphane Chazelas