Wie grep ich rekursiv?


1682

Wie rekursiv rekursiv grepalle Verzeichnisse und Unterverzeichnisse?

find . | xargs grep "texthere" *

110
@ TC1 Das Traurige ist, dass grep selbst die Frage beantworten kann (zumindest GNU grep): grep --help | grep rekursiv
Frank Schmitt

7
Wenn Sie häufig grep verwenden, um rekursive Suchen durchzuführen (insbesondere wenn Sie viele Datei- / Verzeichnisausschlüsse manuell ausführen), ist ack (eine sehr programmiererfreundliche grep-Alternative) möglicherweise hilfreich.
Nick McCurdy

19
Eigentlich weder -r noch - rekursive Arbeit an der Solaris-Box, die ich bei der Arbeit benutze. Und die Manpage für grep erwähnt nichts Rekursives. Ich musste zurückgreifen, um mich selbst zu finden und zu finden.
Ben

8
ag ist mein Lieblingsweg, dies jetzt zu tun github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plfunktioniert bei Redhat Linux nicht. Ich erhalte den Fehler "Keine Übereinstimmung".
Binse

Antworten:


2507
grep -r "texthere" .

Der erste Parameter stellt den regulären Ausdruck dar, nach dem gesucht werden soll, während der zweite das Verzeichnis darstellt, nach dem gesucht werden soll. In diesem Fall .bedeutet das aktuelle Verzeichnis.

Hinweis: Dies funktioniert für GNU grep. Auf einigen Plattformen wie Solaris müssen Sie GNU grep im Gegensatz zur Legacy-Implementierung speziell verwenden. Für Solaris ist dies der ggrepBefehl.


39
Hinweis: "grep -r" funktioniert nur bei neueren Greps. Es funktioniert nicht auf dem Grep, das AIX 5.3zum Beispiel mitgeliefert wird .
Zurückgehalten

110
Verwenden Sie grep -R, um Symlinks zu folgen.
Eloff

53
Es ist gut zu wissen, dass "-i" die Groß- und Kleinschreibung nicht berücksichtigt, und "-n" enthält auch die Zeilennummer für jedes übereinstimmende Ergebnis.
Sadegh

24
Gut zu wissen, wenn Sie nur nach einer festen Zeichenfolge und nicht nach einem regulären Ausdruck suchen, verwenden Sie die Option -F. Sie sparen viel Zeit, wenn Sie den Regex-Parser nicht aufrufen. Sehr praktisch, wenn Sie viele Dateien suchen.
Jeff

6
alias rgrep = 'grep -r'
totten

679

Wenn Sie die Erweiterung oder das Muster der gewünschten Datei kennen, können Sie auch die folgende --includeOption verwenden:

grep -r --include "*.txt" texthere .

Sie können auch Dateien erwähnen, mit denen ausgeschlossen werden soll --exclude.

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. Zum Beispiel ist es standardmäßig rekursiv und ignoriert automatisch die darin aufgeführten Dateien und Verzeichnisse .gitignore, sodass Sie nicht immer dieselben umständlichen Ausschlussoptionen übergeben müssen, um sie zu durchsuchen oder zu suchen.


3
Funktioniert hervorragend mit grep, das mit Linux und Cygwin geliefert wird, aber nicht mit dem, das mit AIX geliefert wird.
Zurückgehalten am

1
@KrzysztofWolny: `` statt =funktioniert unter Ubuntu einwandfrei . PS: Das sollte ein Backticked-Bereich sein, aber der SO-Markdown-Parser ist fehlgeschlagen.
Dan Dascalescu

4
@ DanDascalescu Ich habe für die grep, nicht für die Ag gestimmt , nur damit Sie wissen :)
Bernhard

1
Haben wir die Möglichkeit, ein Verzeichnis bei der rekursiven Suche auszuschließen?
Tom Taylor

Windows Cygwin mag doppelte Anführungszeichen--include "*.txt" --include "*.TXT"
Bob Stein

127

Ebenfalls:

find ./ -type f -print0 | xargs -0 grep "foo"

ist aber grep -reine bessere antwort.


14
Oder wenn Sie sich keine Gedanken über Leerzeichen in Dateinamen machen möchten, find . -type f -exec grep "foo" '{}' \;funktioniert dies gut, wenn dies unterstützt wird.
Edd Steel

4
Wenn Sie die Suche durch xargs an grep weiterleiten möchten UND nur nach einer festen Zeichenfolge suchen (dh nicht nach einem regulären Ausdruck), können Sie möglicherweise die Option grep -F aufrufen, damit grep die reguläre Ausdrucks-Engine nicht lädt für jeden Aufruf. Wenn es viele Dateien gibt, wird es viel schneller sein.
Jeff

2
finden . -Typ f -exec grep -Hu "foo" {} \; ist das, was ich benutze, da es den Dateinamen gibt.
Wes

Dies funktioniert auf allen * nix, weil es POSIX 7 ist
Ciro Santilli 16 16 审查 六四 事件 法轮功

1
find ./ -type f -print0 | xargs -0 grep "foo"
Aehlke

118

Ich benutze jetzt immer (auch unter Windows mit GoW - Gnu unter Windows ):

grep --include="*.xxx" -nRHI "my Text to grep" *

Dazu gehören folgende Optionen:

--include=PATTERN

In Verzeichnissen nur nach übereinstimmenden Dateien suchen PATTERN.

-n, --line-number

Stellen Sie jeder Ausgabezeile die Zeilennummer in der Eingabedatei voran.

(Hinweis: phuclv fügt in den Kommentaren hinzu , was -ndie Leistung erheblich verringert. Daher möchten Sie diese Option möglicherweise überspringen.)

-R, -r, --recursive

Lesen Sie alle Dateien unter jedem Verzeichnis rekursiv. Dies entspricht der -d recurseOption.

-H, --with-filename

Drucken Sie den Dateinamen für jede Übereinstimmung.

-I     

Verarbeiten Sie eine Binärdatei so, als ob sie keine übereinstimmenden Daten enthält.
Dies entspricht der --binary-files=without-matchOption.

Und ich kann ' i' ( -nRHIi) hinzufügen , wenn ich zwischen Groß- und Kleinschreibung unterscheiden möchte.

Ich kann erhalten:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...

Gow sieht vielversprechend aus - neuer als die von mir verwendeten GNU Windows-Dienstprogramme. Ich versuche es jetzt ...
Radim Cernej

Was bedeutet das letzte Zeichen * hier?
Lorniper

2
@lorniper bewirkt, dass die Shell alle Dateien und Ordner in Ihrem aktuellen Verzeichnis auswählt, wodurch der grep wiederum auf diese Dateien und (aufgrund der -ROption rekursiv ) auf die Ordner angewendet wird.
VonC

2
@lorniper Noy genau: *oder .ist ein Glob-Muster (von der Shell interpretiert): unix.stackexchange.com/a/64695/7490 . ' .' wählt auch Punktdateien oder Punktordner aus (wie .git/)
VonC

Früher habe ich immer verwendet, grep -rnIaber dann habe ich gelernt, dass -ndie Leistung stark abnimmt, also benutze ich es nur, wenn es wirklich gebraucht wird, und normalerweise werde ich es verwenden-rI
phuclv

25

In POSIX-Systemen finden Sie keine -rParameter für grepund grep -rn "stuff" .werden nicht ausgeführt. Wenn Sie jedoch den findBefehl verwenden, wird Folgendes ausgeführt:

find . -type f -exec grep -n "stuff" {} \; -print

Einverstanden von Solarisund HP-UX.


Was ist die Bedeutung von {} \; -drucken jeweils?
user1169587

3
In -execOption - Symbol {}ist ein Verweis auf den Dateinamen, der derzeit vom findTool gefunden wird (dh etwas mit dem gefundenen Dateinamen zu tun hat). Außerdem -execsollte die Option mit ;Symbol beendet werden (um das Ende der exec-Befehle zu markieren), aber weil dies alles ist Wenn das Symbol in einer Shell ausgeführt wird, sollte es maskiert werden. Mit der -printOption kann das findTool gefundene Dateinamen auf dem Bildschirm ausdrucken.
Turm

19

Globbing **

Verwenden von grep -rWerken, aber es kann zu viel des Guten sein, insbesondere in großen Ordnern.

Für eine praktischere Verwendung ist hier die Syntax, die die Globbing-Syntax ( **) verwendet:

grep "texthere" **/*.txt

Hiermit werden nur bestimmte Dateien mit einem ausgewählten Muster erfasst. Es funktioniert für unterstützte Shells wie Bash +4 oder zsh .

Führen Sie Folgendes aus, um diese Funktion zu aktivieren : shopt -s globstar.

Siehe auch: Wie finde ich unter Linux alle Dateien, die bestimmten Text enthalten?

git grep

Verwenden Sie für Projekte unter Git-Versionskontrolle:

git grep "pattern"

das ist viel schneller.

ripgrep

Für größere Projekte ist das schnellste Grepping-Tool ripgrep das Dateien standardmäßig rekursiv erfasst:

rg "pattern" .

Es basiert auf der Regex-Engine von Rust, die endliche Automaten, SIMD und aggressive Literaloptimierungen verwendet, um die Suche sehr schnell zu machen. Überprüfen Sie die detaillierte Analyse hier .


3
Vielen Dank für den Vorschlag von git grep - er ist sehr nützlich und ich wusste nichts davon!
Basya

2
Danke für den Ripgrep-Vorschlag. Es ist viel schneller.
Was wäre cool

11

Um den Namen von filesmit pathrekursiv zu finden, der den jeweiligen stringBefehl enthält, verwenden Sie den folgenden Befehl für UNIX:

find . | xargs grep "searched-string"

für Linux:

grep -r "searched-string" .

Suchen Sie eine Datei auf dem UNIXServer

find . -type f -name file_name

Suchen Sie eine Datei auf dem LINUX-Server

find . -name file_name

11

Nur die Dateinamen können ebenfalls nützlich sein

grep -r -l "foo" .

10

Wenn Sie nur tatsächlichen Verzeichnissen und nicht symbolischen Links folgen möchten,

grep -r "thingToBeFound" directory

Wenn Sie symbolischen Links sowie tatsächlichen Verzeichnissen folgen möchten (achten Sie auf unendliche Rekursion),

grep -R "thing to be found" directory

Da Sie versuchen, rekursiv zu greifen, können die folgenden Optionen auch für Sie nützlich sein:

-H: outputs the filename with the line

-n: outputs the line number in the file

Wenn Sie also alle Dateien mit Darth Vader im aktuellen Verzeichnis oder in einem beliebigen Unterverzeichnis suchen und den Dateinamen und die Zeilennummer erfassen möchten, aber nicht möchten, dass die Rekursion symbolischen Links folgt, lautet der Befehl

grep -rnH "Darth Vader" .

Wenn Sie alle Erwähnungen des Wortes Katze im Verzeichnis finden möchten

/home/adam/Desktop/TomAndJerry 

und Sie befinden sich derzeit im Verzeichnis

/home/adam/Desktop/WorldDominationPlot

Wenn Sie den Dateinamen, aber nicht die Zeilennummer einer Instanz der Zeichenfolge "Katzen" erfassen möchten und die Rekursion symbolischen Links folgen soll, wenn sie gefunden werden, können Sie eine der folgenden Aktionen ausführen

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

Quelle:

Ausführen von "grep --help"

Eine kurze Einführung in symbolische Links für alle, die diese Antwort lesen und durch meinen Verweis auf sie verwirrt sind: https://www.nixtutor.com/freebsd/understanding-symbolic-links/


Gute Antwort. Die zusätzlichen Schalter (-rnh) sind sehr hilfreich. Vielen Dank, dass Sie sie vorgeschlagen haben.
semtex41

8

ag ist meine Lieblingsmethode, um dies jetzt zu tun. github.com/ggreer/the_silver_searcher . Es ist im Grunde das Gleiche wie ack, aber mit ein paar weiteren Optimierungen.

Hier ist ein kurzer Benchmark. Ich lösche den Cache vor jedem Test (vgl. Https://askubuntu.com/questions/155768/how-do-i-clean-or-disable-the-memory-cache )

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s


6

Wenn Sie in einer Datei nach einem bestimmten Inhalt in allen Dateien suchen, können Sie diesen verwenden, findda klarer ist, was Sie tun:

find -type f -exec grep -l "texthere" {} +

Beachten Sie, dass -l(Kleinbuchstabe von L) den Namen der Datei anzeigt, die den Text enthält. Entfernen Sie es, wenn Sie stattdessen die Übereinstimmung selbst drucken möchten. Oder verwenden Sie -H, um die Datei mit dem Match zusammenzustellen. Insgesamt sind andere Alternativen:

find -type f -exec grep -Hn "texthere" {} +

Wo -ndruckt die Zeilennummer.


2
Up-Voted als die einzige findLösung, die sowohl unnötige Verwendung xargsals auch Verwendung +anstelle von \;mit -execvermeidet, wodurch Tonnen unnötiger Prozessstarts vermieden werden. :-)
ShadowRanger

6

Dies ist derjenige, der für meinen Fall auf meinem aktuellen Computer funktioniert hat (Git Bash unter Windows 7):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

Ich vergesse immer die -print0 und -0 für Pfade mit Leerzeichen.

BEARBEITEN: Mein bevorzugtes Tool ist jetzt stattdessen ripgrep: https://github.com/BurntSushi/ripgrep/releases . Es ist sehr schnell und hat bessere Standardeinstellungen (wie standardmäßig rekursiv). Gleiches Beispiel wie meine ursprüngliche Antwort, aber mit ripgrep:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (Kündigungsfrist am Ende)

(^ credit: https://stackoverflow.com/a/1987928/1438029 )


Klärung:

grep -r "texthere" /(rekursiv alle Verzeichnisse und Unterverzeichnisse durchsuchen)

grep -r "texthere" .(rekursiv diese Verzeichnisse und Unterverzeichnisse durchsuchen)

grep rekursiv

grep [options] PATTERN [FILE...]

[Optionen]

-R, -r, --recursive

Lesen Sie alle Dateien unter jedem Verzeichnis rekursiv.

Dies entspricht der Option -d recurseoder --directories=recurse.

http://linuxcommand.org/man_pages/grep1.html

grep hilfe

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

Alternativen

ack( http://beyondgrep.com/ )

ag( http://github.com/ggreer/the_silver_searcher )


4

Im Jahr 2018 möchten Sie verwenden ripgrepoder the-silver-searcherweil sie viel schneller als die Alternativen sind.

Hier ist ein Verzeichnis mit 336 Unterverzeichnissen der ersten Ebene:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

Unter OSX wird Folgendes installiert ripgrep: brew install ripgrep. Dies installiert silver-searcher: brew install the_silver_searcher.


Geschwindigkeit ist wichtig, wenn Sie dies häufig tun müssen, aber die meisten von uns tun dies höchstens einige Male im Jahr. Die Installation des neuesten schicken Juju-Tools von Drittanbietern ist übertrieben und die Lösungen, die sich seit 1978 nicht wesentlich geändert haben, sind trotzdem gut zu wissen.
Tripleee

Ich finde es höchst unplausibel, dass ein Programmierer nur mehrmals pro Jahr nach Text in einem Quellbaum sucht. Aber auch unter dem Gesichtspunkt der Benutzerfreundlichkeit rghat ein beträchtlicher Vorteil gegenüber dem Zusammenschustern eines rekursiven grep-Befehls von Grund auf neu. Verwenden von rg: rg foo. Verwenden von Unix-Tools : find . | xargs grep foo. Und wenn eine Ihrer Dateien ein Zitat enthält, müssen Sie verwenden find . -print0 | xargs -0 grep foo. Wirst du dich daran erinnern, wenn du es ein paar Mal im Jahr verwendest?
Hughdbrown

1
Sie vergessen, find . -type f -exec grep 'regex' {} +was in der Tat leicht zu merken ist, wenn Sie diese Tools regelmäßig verwenden. Aber wahrscheinlich sollten Sie trotzdem ctagsoder etagsin Ihrem Quellbaum laufen, wenn Sie häufig nach Dingen suchen müssen.
Tripleee

Ich habe Ripgrep verwendet und es ist großartig. Aber Silver Searcher ist fantastisch für Programmierer. +1
Matt

3

Verwenden Sie in meinem IBM AIX Server (Betriebssystemversion: AIX 5.2):

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

Dadurch werden der Pfad- / Dateiname und die relative Zeilennummer in der Datei wie folgt ausgedruckt:

./inc/xxxx_x.h

2865: / ** Beschreibung: stringYouWannaFind * /

sowieso funktioniert es bei mir :)


3

Unten finden Sie den Befehl zum Stringrekursiven Suchen nach UnixundLinux Umwelt.

für UNIXBefehl ist:

find . -name "string to be searched" -exec grep "text" "{}" \;

für LinuxBefehl ist:

grep -r "string to be searched" .

2

Für eine Liste der verfügbaren Flags:

grep --help 

Gibt alle Übereinstimmungen für den regulären Ausdruck texthere im aktuellen Verzeichnis mit der entsprechenden Zeilennummer zurück:

grep -rn "texthere" .

Gibt alle Übereinstimmungen für texthere zurück , beginnend im Stammverzeichnis, mit der entsprechenden Zeilennummer und ohne Berücksichtigung der Groß- und Kleinschreibung:

grep -rni "texthere" /

hier verwendete Flags:

  • -r rekursiv
  • -n Zeilennummer mit Ausgabe drucken
  • -i Fall ignorieren

1

Ich denke, das ist es, was du schreiben willst

grep myText $(find .)

und dies kann etwas anderes hilfreich sein, wenn Sie die Dateien grep hit finden möchten

grep myText $(find .) | cut -d : -f 1 | sort | uniq

Es ist sehr intuitiv: zum Beispiel: grep -i acc $ (find. -Name "Ausführung *. *")
Yu Shen

1

Ich werfe meine zwei Cent hierher. Wie bereits erwähnt, funktioniert grep -r nicht auf jeder Plattform. Das mag albern klingen, aber ich benutze immer Git.

git grep "texthere"

Auch wenn das Verzeichnis nicht inszeniert ist, inszeniere ich es einfach und verwende git grep.


0

Beachten Sie, dass find . -type f | xargs grep whatever bei verschiedenen Lösungen Fehler auftreten, wenn zu viele Dateien mit find übereinstimmen.

Die beste Wette ist, grep -raber wenn das nicht verfügbar ist, verwenden Sie find . -type f -exec grep -H whatever {} \;stattdessen.


Huh? xargsist speziell eine Problemumgehung für das Problem "Argumentliste zu lang".
Tripleee

2
Nun, nein - xargs ist speziell für die Konvertierung einer Argumentationspipe in eine Arglist gedacht, aber ja, es ist wahr, dass moderne xargs, wenn sie mit -s und / oder -L verwendet werden, mit sehr langen Arglisten umgehen können, indem sie in mehrere Befehlsaufrufe aufbrechen, aber Es ist standardmäßig nicht so konfiguriert (und war in keiner der obigen Antworten enthalten). Als Beispiel:find . -type f | xargs -L 100 grep whatever
m.thome

Auf welcher Plattform wäre das? POSIXxargs ist standardisiert, um dieses Verhalten sofort zu gewährleisten. "Das xargsDienstprogramm muss die Befehlszeilenlänge so begrenzen, dass beim Aufrufen der Befehlszeile die kombinierten Argument- und Umgebungslisten ... {ARG_MAX} -2048 Byte nicht überschreiten."
Tripleee

Hm. Obwohl die gnu-Dokumente auf dieser Basis weniger klar sind als posix und ich keinen Zugriff mehr auf den Computer habe, der mich veranlasst hat, diese Aussage zu treffen, kann ich meine ursprüngliche Interpretation für keine aktuelle Implementierung bestätigen. Rekursives grep ist natürlich immer noch vorzuziehen, wenn es verfügbar ist, aber es gibt wenig Grund, das xargs-Rezept zu vermeiden (verwenden Sie -H für das grep, um zu vermeiden, dass der endgültige Aufruf von grep nur einen einzigen Dateinamen übergibt).
m.thome

0

Nur zum Spaß eine schnelle und schmutzige Suche in * .txt-Dateien, wenn die Antwort von @christangrant zu viel ist, um sie einzugeben :-)

grep -r texthere .|grep .txt


0

Hier ist eine rekursive (leicht mit bash und sh getestete) Funktion, die alle Unterordner eines bestimmten Ordners ($ 1) durchläuft und grepin bestimmten Dateien ($ 2) nach bestimmten Zeichenfolgen ($ 3) sucht:

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

Ausführen und eine Beispielausgabe:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename

-2
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .

7
Dies fügt nicht viel zu anderen Antworten hinzu
Mel
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.