Ich habe beide Befehle ausprobiert und der Befehl find | grep "filename"
ist um ein Vielfaches langsamer als der einfache find "filename"
Befehl.
Was wäre eine richtige Erklärung für dieses Verhalten?
Kommentare
- Sie listen jede Datei mit find auf und übergeben die Daten dann an grep, um sie zu verarbeiten. Mit dem darauf verwendeten find ‚ verpassen Sie den Schritt, jede aufgelistete Datei an grep zu übergeben, um die Ausgabe zu analysieren. Dies wird daher schneller gehen.
- In welchem Sinne langsamer? Dauert die Ausführung der Befehle anders lange?
- Ich kann ‚ dies nicht lokal reproduzieren. Wenn überhaupt, meldet
time find "$HOME" -name '.profile'
eine längere Zeit alstime find "$HOME" | grep -F '.profile'
. (17s vs. 12s). - @JenniferAnderson Ich habe beide wiederholt ausgeführt. Die 17 und 12 Sekunden sind Durchschnittswerte. Und ja, die
grep
-Variante stimmt mit einer beliebigen Stelle imfind
-Ergebnis überein, während sie mitfind -name
würde nur genau übereinstimmen (in diesem Fall). - Ja,
find filename
wäre schnell . Ich nahm an, dass dies ein Tippfehler war und dass das OPfind -name filename
bedeutete. Mitfind filename
wird nurfilename
untersucht (und sonst nichts).
Antwort
(Ich gehe hier von GNU find
aus)
Verwenden Sie nur
find filename
wäre schnell, da nur filename
oder die Namen in filename
, wenn es sich um ein Verzeichnis handelt, oder ein Fehler, wenn dieser Name im aktuellen Verzeichnis nicht vorhanden war. Es ist eine sehr schnelle Operation, ähnlich wie ls filename
(aber rekursiv, wenn filename
ein Verzeichnis ist).
In Im Gegensatz dazu würde
find | grep filename
es find
ermöglichen, eine Liste von allen Namen zu generieren Das aktuelle Verzeichnis und darunter, das dann grep
filtern würde. Dies wäre offensichtlich eine viel langsamere Operation.
Ich gehe davon aus, dass es sich tatsächlich um handelt beabsichtigt war
find . -type f -name "filename"
Dies würde nach filename
als Namen einer regulären Datei irgendwo in suchen das aktuelle Verzeichnis oder darunter.
Dies ist genauso schnell (oder vergleichsweise schnell) wie find | grep filename
, aber das grep
Die Lösung würde filename
mit dem vollständigen Pfad jedes gefundenen Namens abgleichen, ähnlich wie -path "*filename*"
mit .
Die Verwirrung beruht auf einem Missverständnis darüber, wie find
funktioniert.
Das Dienstprogramm verwendet eine Reihe von Pfaden und gibt alle Namen unter diesen Pfaden zurück.
Sie können dann Beschränken Sie die zurückgegebenen Namen mithilfe verschiedener Tests, die sich auf den Dateinamen, den Pfad, den Zeitstempel, die Dateigröße, den Dateityp usw. auswirken können.
Wenn Sie
find a b c
Sie bitten find
, jeden unter den drei Pfaden verfügbaren Namen aufzulisten a
, b
und c
. Wenn dies zufällig Namen von regulären Dateien im aktuellen Verzeichnis sind, werden diese zurückgegeben. Wenn einer von ihnen zufällig der Name eines Verzeichnisses ist, wird er zusammen mit allen weiteren Namen in diesem Verzeichnis zurückgegeben.
Wenn ich
find . -type f -name "filename"
Dies generiert eine Liste aller Namen im aktuellen Verzeichnis (.
) und darunter. Dann beschränkt es die Namen auf die von regulären Dateien, d. H. Nicht Verzeichnissen usw., mit -type f
. Dann gibt es eine weitere Einschränkung für Namen, die mit filename
unter Verwendung von -name "filename"
übereinstimmen. Die Zeichenfolge filename
kann ein Dateinamen-Globbing-Muster sein, z. B. *.txt
(denken Sie daran, es zu zitieren!).
Beispiel:
Im Folgenden wird die Datei mit dem Namen .profile
in meinem Ausgangsverzeichnis „gefunden“:
$ pwd /home/kk $ find .profile .profile
Tatsächlich werden jedoch nur alle Namen im Pfad .profile
zurückgegeben (es gibt nur einen Namen, und dieser gehört zu dieser Datei).
Dann cd
eine Ebene höher und versuche es erneut:
$ cd .. $ pwd /home $ find .profile find: .profile: No such file or directory
Die find
kann jetzt keinen Pfad mit dem Namen .profile
finden.
Wenn ich jedoch das aktuelle Verzeichnis anzeigen und die zurückgegebenen Namen auf .profile
beschränken soll, wird es gefunden es auch von dort:
$ pwd /home $ find . -name ".profile" ./kk/.profile
Kommentare
-
find filename
würde nurfilename
zurückgeben, wennfilename
nicht vom Typ Verzeichnis (oder vom Typ Verzeichnis, aber hatte selbst keinen Eintrag)
Antwort
Nicht-technische Erklärung: Suche nach Jack in einer Menschenmenge ist schneller als nach allen in einer Menschenmenge zu suchen und alle außer Jack aus der Überlegung auszuschließen.
Kommentare
- Das Problem ist, dass das OP Jack erwartet sei die einzige Person in der Menge. Wenn ja, haben sie ‚ Glück.
find jack
listetjack
auf, wenn ‚ eine Datei mit dem Namen oder alle Namen im Verzeichnis, wenn ‚ ein Verzeichnis ist. ‚ ist ein Missverständnis darüber, wiefind
funktioniert.
Antwort
Ich habe das Problem noch nicht verstanden, kann aber weitere Erkenntnisse liefern.
Wie bei Kusalananda der Aufruf find | grep
ist auf meinem System deutlich schneller, was wenig Sinn macht. Zuerst nahm ich eine Art Pufferproblem an; Das Schreiben in die Konsole verlangsamt die Zeit bis zum nächsten Systemaufruf zum Lesen des nächsten Dateinamens. Das Schreiben in eine Pipe ist sehr schnell: etwa 40 MB / s, selbst für 32-Byte-Schreibvorgänge (auf meinem eher langsamen System; 300 MB / s für eine Blockgröße von 1 MB). Daher habe ich angenommen, dass find
beim Schreiben in eine Pipe (oder Datei) schneller aus dem Dateisystem lesen kann, sodass die beiden Vorgänge zum Lesen von Dateipfaden und zum Schreiben in die Konsole parallel ausgeführt werden können ( was find
als einzelner Thread-Prozess nicht alleine tun kann.
Es ist find
„
Vergleichen der beiden Aufrufe
:> time find "$HOME"/ -name "*.txt" >/dev/null real 0m0.965s user 0m0.532s sys 0m0.423s
und
:> time find "$HOME"/ >/dev/null real 0m0.653s user 0m0.242s sys 0m0.405s
zeigt, dass find
etwas unglaublich Dummes tut (was auch immer das sein mag) Es stellt sich heraus, dass die Ausführung von -name "*.txt"
ziemlich inkompetent ist.
Kann vom Eingabe / Ausgabe-Verhältnis
Sie könnten denken, dass find -name
gewinnt, wenn es sehr wenig zu schreiben gibt. Aber es wird nur peinlicher für find
. Es verliert, auch wenn überhaupt nichts zu schreiben ist gegen 200K-Dateien (13M Pipe-Daten) für grep
:
time find /usr -name lwevhewoivhol
find
kann so schnell sein wie grep
, obwohl
Es stellt sich heraus, dass sich die Dummheit von find
mit name
nicht auf andere Tests erstreckt. Verwenden Sie stattdessen einen regulären Ausdruck, und das Problem ist behoben:
:> time find "$HOME"/ -regex "\.txt$" >/dev/null real 0m0.679s user 0m0.264s sys 0m0.410s
Ich denke, dies kann als Fehler angesehen werden. Ist jemand bereit, einen Fehlerbericht einzureichen? Meine Version ist find (GNU findutils) 4.6.0
Kommentare
- Wie wiederholbar sind Ihre Timings? Wenn Sie zuerst den Test
-name
durchgeführt haben, war er möglicherweise langsamer, da der Verzeichnisinhalt nicht zwischengespeichert wurde. (Beim Testen von-name
und-regex
stelle ich fest, dass sie ungefähr dieselbe Zeit in Anspruch nehmen, zumindest wenn der Cache-Effekt berücksichtigt wurde Natürlich kann es sich nur um eine andere Version vonfind
…) - @psmears handeln. Natürlich habe ich diese Tests mehrmals durchgeführt. Das Caching-Problem wurde bereits in den Kommentaren zur Frage vor der ersten Antwort erwähnt. Meine
find
-Version ist find (GNU findutils) 4.6.0 - Warum ist es überraschend, dass das Hinzufügen von
-name '*.txt'
langsamer wirdfind
? Es muss zusätzliche Arbeit leisten und jeden Dateinamen testen. - @Barmar Einerseits kann diese zusätzliche Arbeit extrem schnell erledigt werden. Andererseits spart diese zusätzliche Arbeit andere Arbeit.
find
muss weniger Daten schreiben. Das Schreiben in eine Pipe ist viel langsamer. - Das Schreiben auf eine Festplatte ist sehr langsam. Das Schreiben in eine Pipe ist nicht so schlecht, es wird nur in einen Kernelpuffer kopiert. Beachten Sie, dass in Ihrem ersten Test beim Schreiben von mehr in
/dev/null
weniger Systemzeit verwendet wurde.
Antwort
Hinweis : Ich gehe davon aus, dass Sie find . -name filename
(andernfalls suchen Sie nach verschiedenen Dingen; find filename
untersucht tatsächlich einen Pfad namens filename , der enthält möglicherweise fast keine Dateien und wird daher sehr schnell beendet.
Angenommen, Sie haben ein Verzeichnis mit fünftausend Dateien. Auf den meisten Dateisystemen werden diese Dateien tatsächlich in einer tree -Struktur gespeichert, mit der eine bestimmte Datei schnell gefunden werden kann. P. >
Wenn Sie also find
bitten, eine Datei zu suchen, deren Name nur überprüft werden muss, fragt find
für diese Datei und nur diese Datei in das zugrunde liegende Dateisystem, das nur sehr wenige Seiten aus dem Massenspeicher liest. Wenn das Dateisystem also sein Geld wert ist, wird dieser Vorgang viel schneller ausgeführt als den gesamten Baum durchlaufen , um alle Einträge abzurufen.
Wenn Sie nach find
fragen, aber genau das tun Sie, durchlaufen Sie den gesamten Baum und lesen. Jeder einzelne Eintrag. Mit großen Verzeichnissen, Dies könnte ein Problem sein (genau aus diesem Grund erstellen mehrere Softwareprogramme, die viele Dateien auf der Festplatte speichern müssen, „Verzeichnisbäume“ mit einer Tiefe von zwei oder drei Komponenten: Auf diese Weise muss jedes einzelne Blatt nur weniger Dateien enthalten.)
Antwort
Nehmen wir an, dass die Datei / john / paul / george / ringo / beatles existiert und die gesuchte Datei heißt „Steine“
find / stones
find vergleicht „Beatles“ mit „Steinen“ und lässt sie fallen, wenn „s“ und „b“ nicht übereinstimmen .
find / | grep stones
In diesem Fall wird „/ john / paul / george / ringo / beatles“ an grep und grep wil übergeben Ich muss mich durch den gesamten Pfad arbeiten, bevor ich feststellen kann, ob es eine Übereinstimmung ist.
grep erledigt daher viel mehr Arbeit, weshalb es länger dauert.
Kommentare
- Haben Sie es versucht?
- Die Kosten für die Zeichenfolgenvergleiche (extrem einfach und billig) werden durch die E / A-Kosten (oder nur für den Systemaufruf, wenn zwischengespeichert) vollständig in den Schatten gestellt
- grep isn ‚ ta String-Vergleich, sein Vergleich mit regulären Ausdrücken, was bedeutet, dass er sich durch den gesamten String arbeiten muss, bis er einen findet ein Match oder erreicht das Ende. Die Verzeichnissuchen sind gleich, egal was passiert.
- @Paranoid Hm, über welche Version von find sprechen Sie? Es ‚ ist anscheinend nichts wie das find , das ich ‚ im Debian gewohnt bin.