grep -R
(mit Ausnahme des modifizierten GNU, grep
das unter OS / X 10.8 und höher zu finden ist) folgt Symlinks. Selbst wenn nur 100 GB Dateien enthalten sind ~/Documents
, ist möglicherweise immer noch ein Symlink zu vorhanden, /
und Sie werden das gesamte Dateisystem einschließlich der Dateien durchsuchen wie /dev/zero
. Verwenden Sie grep -r
mit neueren GNU grep
, oder verwenden Sie die Standardsyntax:
find ~/Documents -type f -exec grep Milledgeville /dev/null {} +
(Beachten Sie jedoch, dass der Beendigungsstatus nicht die Tatsache widerspiegelt, dass das Muster übereinstimmt oder nicht).
grep
Findet die Linien, die dem Muster entsprechen. Dazu muss jeweils eine Zeile in den Speicher geladen werden. GNU hat grep
im Gegensatz zu vielen anderen grep
Implementierungen keine Begrenzung für die Größe der gelesenen Zeilen und unterstützt die Suche in Binärdateien. Wenn Sie also eine Datei mit einer sehr großen Zeile haben (dh mit zwei Zeilenumbrüchen, die sehr weit entfernt sind), die größer als der verfügbare Speicher ist, schlägt der Vorgang fehl.
Das passiert normalerweise mit einer spärlichen Datei. Sie können es reproduzieren mit:
truncate -s200G some-file
grep foo some-file
Das ist schwer zu umgehen. Du könntest es so machen (immer noch mit GNU grep
):
find ~/Documents -type f -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} +
Das konvertiert Sequenzen von NUL-Zeichen in ein Newline-Zeichen, bevor die Eingabe an übergeben wird grep
. Dies gilt für Fälle, in denen das Problem auf spärliche Dateien zurückzuführen ist.
Sie können es optimieren, indem Sie es nur für große Dateien ausführen:
find ~/Documents -type f \( -size -100M -exec \
grep -He Milledgeville {} + -o -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} + \)
Wenn die Dateien nicht spärlich , und Sie haben eine Version von GNU grep
vor 2.6
, können Sie die Verwendung --mmap
Option. Die Zeilen werden nicht kopiert, sondern im Speicher abgelegt. Das bedeutet, dass das System den Speicher jederzeit durch Auslagern der Seiten in die Datei freischalten kann. Diese Option wurde in GNU grep
2.6 entfernt
grep
können die bisher verarbeiteten Puffer verworfen werden. Sie könnengrep
die Ausgabe aufyes
unbestimmte Zeit ausführen, ohne mehr als ein paar Kilobyte Speicher zu belegen. Das Problem ist die Größe der Linien.--null-data
Option kann auch hier nützlich sein. Erzwingt die Verwendung von NUL anstelle von Newline als Eingabezeilenabschluss.Normalerweise mache ich
Ich habe eine Reihe von Methoden ausprobiert und fand, dass dies die schnellste ist. Beachten Sie, dass dies Dateien mit Leerzeichen, die den Dateinamen enthalten, nicht sehr gut behandelt. Wenn Sie wissen, dass dies der Fall ist und eine GNU-Version von grep haben, können Sie Folgendes verwenden:
Wenn nicht, können Sie Folgendes verwenden:
Welches wird
exec
ein Grep für jede Datei.quelle
find -print0 | xargs -0 grep -ne 'expression'
find -print0
undxargs -0
bis jetzt angenommen: alle drei BSD, MINIX 3, Solaris 11, ...Ich kann mir ein paar Möglichkeiten vorstellen, um das zu umgehen:
Anstatt alle Dateien auf einmal zu prüfen, sollten Sie immer nur eine Datei gleichzeitig ausführen. Beispiel:
Wenn Sie nur wissen müssen, welche Dateien die Wörter enthalten, tun Sie dies
grep -l
stattdessen. Da grep dort nach dem ersten Treffer aufhört zu suchen, muss es keine riesigen Dateien mehr lesenWenn Sie auch den eigentlichen Text haben möchten, können Sie zwei separate Greps aneinanderreihen:
quelle
grep
Ausgabe ein Begrenzer verwendet wird, der in Dateinamen zulässig ist). Sie müssen auch zitieren$file
.for
, dass die Datei als zwei Argumente verarbeitet wird)Ich greife nach einer 6-TB-Festplatte, um nach verlorenen Daten zu suchen, und der Speicher ist erschöpft. Dies sollte auch für andere Dateien funktionieren.
Die Lösung, die wir gefunden haben, bestand darin, die Festplatte mit dd in Chunks zu lesen und die Chunks zu sperren. Dies ist der Code (big-grep.sh):
quelle