Ich habe ein Verzeichnis mit ca. 26.000 Dateien und muss alle diese Dateien einlesen. Das Problem ist, dass ich es so schnell wie möglich brauche, daher ist es nicht ideal, ein Skript zu erstellen, in dem grep den Namen einer Datei aus dem Befehl find entnimmt und Übereinstimmungen in die Datei schreibt. Bevor das Problem "Argumente sind zu lang" auftrat, dauerte es ca. 2 Minuten, bis alle diese Dateien eingespielt waren. Irgendwelche Ideen, wie es geht? Bearbeiten: Es gibt ein Skript, das ständig neue Dateien erstellt. Daher ist es nicht möglich, alle Dateien in verschiedenen Verzeichnissen abzulegen.
files
grep
performance
user2778979
quelle
quelle
find
mitxargs
odergrep -R
Antworten:
Mit
find
:( Dient
-type f
nur zum Suchen in regulären Dateien (auch ohne Symlinks, selbst wenn sie auf reguläre Dateien verweisen). Wenn Sie in einem beliebigen Dateityp außer Verzeichnissen suchen möchten (aber beachten Sie, dass es einige Dateitypen wie fifos oder / dev / zero gibt) im allgemeinen mögen Sie nicht lesen), ersetzen Sie-type f
mit dem GNU-spezifischen! -xtype d
(-xtype d
Einstimmungen für Dateien vom Typ Verzeichnis nach Symlink Auflösung)).Mit GNU
grep
:(Beachten Sie jedoch, dass, sofern Sie keine neuere Version von GNU grep haben, beim Abstieg in Verzeichnisse Symlinks folgen). Nicht reguläre Dateien werden nur durchsucht, wenn Sie eine
-D read
Option hinzufügen . Neuere Versionen von GNUgrep
werden jedoch immer noch nicht in Symlinks suchen.Sehr alte Versionen von GNU
find
haben die Standardsyntax nicht unterstützt{} +
, aber dort können Sie die nicht standardmäßige verwenden:Performances sind wahrscheinlich I / O-gebunden. Dies ist die Zeit, die für die Suche benötigt wird, um alle diese Daten aus dem Speicher zu lesen.
Wenn sich die Daten auf einem redundanten Festplattenarray befinden, kann das gleichzeitige Lesen mehrerer Dateien die Leistung verbessern (und sie ansonsten beeinträchtigen). Wenn die Leistung nicht an E / A gebunden ist (weil sich beispielsweise alle Daten im Cache befinden) und Sie über mehrere CPUs verfügen, kann die gleichzeitige
greps
Ausführung ebenfalls hilfreich sein. Sie können dies mitxargs
der-P
Option von GNU tun .Zum Beispiel, wenn sich die Daten auf einem RAID1-Array mit 3 Laufwerken befinden oder wenn sich die Daten im Cache befinden und Sie 3 CPUs haben, deren Zeit übrig bleibt:
(Hier wird alle 1000 Dateien
-n1000
eine neuegrep
Datei erzeugt, bis zu 3 gleichzeitig).Beachten Sie jedoch, dass Sie, wenn die Ausgabe von
grep
umgeleitet wird, eine schlecht verschachtelte Ausgabe der dreigrep
Prozesse erhalten. In diesem Fall möchten Sie sie möglicherweise ausführen als:(auf einem aktuellen GNU- oder FreeBSD-System) oder verwenden Sie die
--line-buffered
Option von GNUgrep
.Wenn
pattern
es sich um eine feste Zeichenfolge handelt, kann das Hinzufügen der-F
Option die Situation verbessern.Wenn es sich nicht um Mehrbytezeichendaten handelt oder wenn für die Übereinstimmung dieses Musters keine Rolle spielt, ob es sich um Mehrbytezeichen handelt oder nicht, dann gilt Folgendes:
könnte die Leistung erheblich verbessern.
Wenn Sie solche Suchanfragen häufig durchführen, möchten Sie Ihre Daten möglicherweise mithilfe einer der vielen Suchmaschinen indizieren.
quelle
26000 Dateien in einem einzigen Verzeichnis sind für die meisten Dateisysteme eine Menge. Es ist wahrscheinlich, dass das Lesen dieses großen Verzeichnisses einen erheblichen Teil der Zeit in Anspruch nimmt. Teilen Sie es in kleinere Verzeichnisse mit jeweils nur ein paar hundert Dateien auf.
Ein Anruf
find
kann eine schlechte Leistung nur erklären, wenn Sie es falsch machen. Auf diese Weise können Sie schnell ein Verzeichnis durchsuchen und sicherstellen, dass Sie nicht riskieren, eine zu lange Befehlszeile auszuführen. Stellen Sie sicher, dass Sie verwenden-exec grep PATTERN {} +
, dass so viele Dateien wie möglich pro Befehlsaufruf gepackt werden und nicht-exec grep PATTERN {} \;
, dassgrep
der Befehl einmal pro Datei ausgeführt wird: Die Ausführung des Befehls einmal pro Datei ist wahrscheinlich erheblich langsamer.quelle
Wenn Sie ALLE Dateien mehrmals durchsuchen müssen (wie Sie sagten, indem Sie ein Skript ausführen), würde ich vorschlagen, dass Sie sich die RAM-Datenträger ansehen, alle Dateien dort kopieren und die Dateien dann mehrmals durchsuchen. Dies beschleunigt Ihre Suche um den Faktor 1 mindestens 100x.
Du brauchst nur genug RAM. Andernfalls sollten Sie sich mit der Indizierung der Dateien befassen, z. in lucene oder eine nosql-datenbank und dann abfragen dazu ausführen.
quelle
grep
. Es gibt auch den Punkt, dass: "Es gibt ein Skript, das ständig neue Dateien erstellt, so dass es nicht möglich ist, alle Dateien in verschiedenen Verzeichnissen abzulegen."Alle Dateien im Verzeichnis
mit rekursiv
quelle
.
anstelle von verwendet hätten*
).*
schließt Punktdateien aus (obwohl mit -R, nicht die in den rekursiven Verzeichnissen). -R im Gegensatz zu -r folgt Symlinks auch mit neueren Versionen von GNU grep. Sie haben auch ein Problem mit Dateien im aktuellen Verzeichnis, deren Name mit-