Ich bin mir nicht sicher:
grep -r -i 'the brown dog' /*
ist wirklich das, was du meintest. Das würde bedeuten, dass alle nicht ausgeblendeten Dateien und Verzeichnisse rekursiv mit grep versehen werden /
(aber immer noch in ausgeblendeten Dateien und Verzeichnissen nachsehen).
Angenommen, Sie meinten:
grep -r -i 'the brown dog' /
Ein paar Dinge zu beachten:
- Nicht alle
grep
Implementierungen werden unterstützt -r
. Und unter denen, die dies tun, unterscheiden sich die Verhaltensweisen: Einige folgen beim Durchlaufen des Verzeichnisbaums Symlinks zu Verzeichnissen (was bedeutet, dass Sie möglicherweise mehrmals in derselben Datei suchen oder sogar in Endlosschleifen ausgeführt werden), andere nicht. Einige schauen in Gerätedateien (und es wird /dev/zero
zum Beispiel einige Zeit in Anspruch nehmen) oder Pipes oder Binärdateien ..., andere nicht.
- Es ist effizient, da es
grep
beginnt, Dateien zu durchsuchen, sobald es sie entdeckt. Aber während es in einer Datei aussieht, sucht es nicht mehr nach weiteren Dateien, in denen gesucht werden kann (was in den meisten Fällen wahrscheinlich genauso gut ist).
Ihre:
find / -type f -exec grep -i 'the brown dog' {} \;
(Entfernt das, -r
was hier keinen Sinn machte) ist schrecklich ineffizient, weil Sie eins grep
pro Datei ausführen. ;
sollte nur für Befehle verwendet werden, die nur ein Argument akzeptieren. Außerdem wird hier grep
der Dateiname nicht gedruckt , da nur in einer Datei gesucht wird, sodass Sie nicht wissen, wo die Übereinstimmungen sind.
Sie suchen nicht in Gerätedateien, Pipes, Symlinks ..., Sie folgen keinen Symlinks, aber Sie suchen möglicherweise immer noch in Dingen wie /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
wäre viel besser, weil so wenig grep
Befehle wie möglich ausgeführt würden. Sie würden den Dateinamen erhalten, es sei denn, der letzte Lauf hat nur eine Datei. Dafür ist es besser zu verwenden:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
oder mit GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Beachten Sie, dass der grep
Vorgang erst gestartet wird, wenn find
genügend Dateien zum Kauen gefunden wurden, sodass es zu einer anfänglichen Verzögerung kommt. Und find
wird nicht weiter nach weiteren Dateien suchen, bis die vorherige grep
zurückgekehrt ist. Das Zuweisen und Weitergeben der großen Dateiliste hat einige (wahrscheinlich zu vernachlässigende) Auswirkungen. Alles in allem wird es also wahrscheinlich weniger effizient sein als ein grep -r
, das nicht dem Symlink folgt oder nicht in Geräte hineinschaut.
Mit GNU-Tools:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Wie oben beschrieben, werden so wenige grep
Instanzen wie möglich ausgeführt, es find
wird jedoch weiterhin nach weiteren Dateien gesucht, während der erste grep
Aufruf im ersten Stapel ausgeführt wird. Das kann ein Vorteil sein oder auch nicht. Wenn beispielsweise Daten auf rotierenden Festplatten gespeichert sind find
und grep
auf Daten zugegriffen wird, die an verschiedenen Stellen auf der Platte gespeichert sind, wird der Plattendurchsatz verlangsamt, indem der Plattenkopf sich ständig bewegt. In einem RAID - Setup (wo find
und grep
verschiedene Datenträger zugreifen kann) oder auf SSDs, das könnte einen positiven Unterschied machen.
In einem RAID-Setup können durch Ausführen mehrerer gleichzeitiger grep
Aufrufe ebenfalls Verbesserungen erzielt werden. Immer noch mit GNU-Tools auf RAID1-Speicher mit 3 Festplatten,
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
könnte die Leistung erheblich steigern. Beachten Sie jedoch, dass der zweite Befehl grep
erst gestartet wird, wenn genügend Dateien gefunden wurden, um den ersten grep
Befehl auszufüllen . Sie können eine -n
Option hinzufügen xargs
, damit dies früher geschieht (und weniger Dateien pro grep
Aufruf übergeben werden).
Beachten Sie auch, dass, wenn Sie die xargs
Ausgabe an etwas anderes als ein Endgerät umleiten , die greps
s beginnen, ihre Ausgabe zu puffern, was bedeutet, dass die Ausgabe dieser grep
s wahrscheinlich falsch verschachtelt wird. Sie müssten sie verwenden stdbuf -oL
(wo verfügbar wie unter GNU oder FreeBSD), um das zu umgehen (Sie haben möglicherweise immer noch Probleme mit sehr langen Zeilen (normalerweise> 4 KB)), oder jeder muss seine Ausgabe in eine separate Datei schreiben und diese verketten alles am Ende.
Hier ist die Zeichenfolge, nach der Sie suchen, fest (kein regulärer Ausdruck), daher kann die Verwendung der -F
Option einen Unterschied bewirken (es ist unwahrscheinlich, dass grep
Implementierungen bereits wissen, wie sie dies optimieren können).
Eine andere Sache, die einen großen Unterschied machen könnte, ist das Fixieren des Gebietsschemas auf C, wenn Sie sich in einem Mehrbyte-Gebietsschema befinden:
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
Um einen Blick hinein zu vermeiden /proc
, /sys
... verwenden Sie -xdev
die Dateisysteme, in denen Sie suchen möchten , und geben Sie sie an:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Oder kürzen Sie die Pfade, die Sie explizit ausschließen möchten:
LC_ALL=C find / \( -path /dev -o -path /proc -o -path /sys \) -prune -o \
-type f -exec grep -i 'the brown dog' /dev/null {} +