Wie finde ich Text in einer Datei und lasse sie mehrere Unterordner durchsuchen?

7

Ich suche nach einem Funktionsnamen und die Ordnerstruktur ist tief und es gibt viele Dateien zu suchen.

Normalerweise gehe ich mit so etwas wie, find * | grep functionnameaber ist das der beste Weg?

tooshel
quelle
Duh was? findfindet nur Dateinamen , nicht Inhalt.
Hallo71
Schon mal was gehört xargs? Oder die -execprimäre in find?
Geekosaurier
Hey Mann, ich sagte, das habe ich benutzt, nicht, dass es funktioniert hat! Warum fragst du mich wohl? Außerdem war es "so etwas wie", weil ich es nie zum Laufen bringen konnte und nach dem xargs-Teil suchen musste.
Tooshel
Entschuldigung, diese Bemerkung war an @ Hello71 gerichtet. Ich gewöhne mich immer noch an die StackExchange-Etikette.
Geekosaurier
Schauen Sie sich diesen Beitrag an: theunixshell.blogspot.in/2014/03/…
Vijay

Antworten:

15
$ find . -type f -print0 | xargs -0 grep foo
$ grep -r foo . # GNU grep only

und in zshmit setopt extendedglob,

$ grep foo **/*(.)
Geekosaurier
quelle
Besser : find . -type f -print0 | xargs -0 grep /dev/null foo, damit grepimmer der passende Dateiname gedruckt wird. Oder find . -type f -exec grep /dev/null {} +für Implementierungen, die POSIX.2004 eingeholt haben (was derzeit OpenBSD ausschließt).
Gilles 'SO - hör auf böse zu sein'
Ich kann immer noch nicht glauben, dass es keinen einfacheren Weg gibt, dies zu tun. Und ich habe das "grep -r" ausprobiert und es hat nicht funktioniert. Warum ist es nur GNU grep und warum ist das nicht auf mehr Systemen?
Tooshel
1
Weil traditionell grepes nicht hatte (die Idee war, dass, wenn Sie Rekursion wollten, Sie findmit verwendet haben grep) und das Hinzufügen nachträglich zu Systemen, die seit Jahren funktionieren, Dinge brechen könnte. (GNU grepverhält sich nicht ganz identisch mit zB System V. grep)
Geekosaurier
5

Es gibt auch ack, die speziell für diese Art von Aufgaben entwickelt wurde und die Unterordnersuche automatisch durchführt.

Alex
quelle
Und da ist auch agwas viel schneller ist als ack.
mmoya
2

Als Alternative zu den find | xargsAntworten können Sie auch die Verwendung von ctags in Betracht ziehen, da Sie nicht nach Text, sondern speziell nach Funktionsnamen suchen.

Um dies zu tun, würden Sie ctagsgegen Ihre Quelle laufen , um eine TAGSDatei zu erstellen , und dann grepgegen die TAGSDatei, die Zeilen im folgenden Format ausspuckt:

{tagname}<Tab>{tagfile}<Tab>{tagaddress}

Wo tagnamewird der Funktionsname enthalten, tagfileist die Datei, in der es sich befindet, und tagaddresswird ein vi-Befehl sein, um zu dieser Zeile zu gelangen. (Könnte nur eine Zeilennummer sein.)

(Gibt es eine einfache Möglichkeit, mit den verschiedenen von Eclipse erstellten Indizes etwas Ähnliches zu tun oder einfach die Eclipse-Datenbank abzufragen?)

Jerry Asher
quelle
1

Was ist los mit grep -r(== grep --recursive)? Vermisse ich hier etwas?

(+1 ackauch - ich benutze regelmäßig beide)

edit: Ich habe einen ausgezeichneten Artikel gefunden, der die Möglichkeiten und Fallstricke beschreibt, wenn Sie nicht GNU grep hier haben . Aber im Ernst, wenn Sie nicht zur GNU grepVerfügung haben, wird das Erhalten acknoch mehr empfohlen.

Simon
quelle
Ja, anscheinend hat nicht jeder die schicke Version von grep.
Tooshel
@tooshel - wusste nicht, dass die Nicht-GNU grepdiese Option nicht hat. aktualisierte meine Antwort :)
Simon
-bash: ack: Befehl nicht gefunden
tooshel
Okay, ich habe die Anweisungen zur Installation von ack gelesen. . . und ich habe es einfach in / bin geworfen, damit jeder es benutzen kann. War das eine schlechte Idee?
Tooshel
@tooshel: nur wenn du nicht willst, dass jeder es benutzen kann ...!
Simon
0

find . | xargs grep schlägt bei Dateinamen mit Leerzeichen fehl:

> echo test > "a b c"
> find . | xargs grep test
grep: ./a: No such file or directory
grep: b: No such file or directory
grep: c: No such file or directory

Beachten Sie, dass auch -print0 dieses Problem hat.

Meiner Meinung nach ist es besser, -exec grepmit find zu arbeiten, das alle Dateinamen intern behandelt und dieses Problem vermeidet:

> find . -exec grep test {} \;
test
>
JRW
quelle
1
find … -print0 | xargs -0 …kommt mit beliebigen Dateinamen zurecht. Alle POSIX.2004-kompatiblen Implementierungen von findallow find … -exec … {} +, die den Befehl mit mehreren Dateien gleichzeitig aufrufen . Ein besserer Befehl ist find . -type f -exec grep test /dev/null {} +; Das Hinzufügen von /dev/nullist so, dass grepder Dateiname konsistent gedruckt wird, wenn eine Übereinstimmung gefunden wird.
Gilles 'SO - hör auf böse zu sein'
0

Wenn Ihre Festplatten schnell sind, möchten Sie möglicherweise das grep parallelisieren:

find . -type f -print0 | parallel -0 grep foo

Sehen Sie sich das Intro-Video an, um mehr über GNU Parallel zu erfahren: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
quelle
0

$ find -type f -print0 | xargs -r0 grep foo

-rin xargsvermeidet die Ausführung des Befehls, wenn keine Eingabe erfolgt ist. Es ist eine GNU-Erweiterung.

Es gibt auch agwelche speziell dafür entwickelt wurden und viel besser als ack. Es ist in den neuesten Debian / Ubuntu-Versionen im Paket silversearcher-ag verfügbar .

mmoya
quelle