Warum ist find exec grep> file eine Endlosschleife?

1650
Hammer Bro.

Ich habe versucht, alle Message-ID: Header (Zeilen) in einem Verzeichnis mit 200K .eml-Dateien (Nur-Text) zu sammeln. Ein bisschen naiv sagte ich:

find -type f -exec grep -Fi "message-id:" {} \; > messageids.txt 

Ich ließ es über Nacht laufen, da ich dachte, es würde eine Weile dauern, bis ich so viele Dateien durchforstete. Ein bisschen zu meiner Überraschung heute morgen ist messageids.txt 1.7 TB und meine Partition ist voll. Mir ist klar, dass das, was passiert sein muss, ist, dass die eigene Ausgabe von grep als Eingabe aufgegriffen wird, aber ich würde nicht (und würde es auch immer noch nicht intuitiv erwarten), dass sich dies endlos wiederholt. Was bedeutet, dass mein Verständnis der Kräfte nicht so stark ist, wie es sein sollte.

Kann jemand eine detaillierte Erklärung dazu liefern, wie der Befehl oben funktioniert und warum diese Endlosschleife erwartet werden sollte (nehme ich an)? Vielen Dank.

Update: Ich erwarte, dass es funktioniert, dass find eine Liste von Dateien findet und auf jeder von ihnen grep heißt. Irgendwann wird grep auf messageids.txt aufgerufen. Wenn ich dies beispielsweise für einen Sortierbefehl ausführen würde, würde messageids.txt erstellt, sobald der Befehl ausgeführt wird (möglicherweise wird er geknackt, falls er bereits vorhanden war), er wurde jedoch nicht gefüllt, bis der Befehl ausgeführt wurde. In diesem Fall muss, damit die Schleife unendlich ist, die Datei gefüllt werden, bevor die Ausgabe abgeschlossen ist, jedoch auf eine Weise, dass die Eingabe von grep ständig aufrechterhalten wird. Das ist der Punkt, der sich nicht so verhält, wie ich es erwartet hätte, und ich hoffte auf eine detaillierte Erklärung, wie diese Prozesskette abläuft, damit ich meine Linux-Grundlagen festigen kann.

2

2 Antworten auf die Frage

3
David Schwartz

Jedes Mal, wenn es eine Zeile darin findet message-id, schreibt es sie bald darauf messageids.txt. Und jedes Mal, wenn eine Zeile message-iddarin geschrieben wird, messageids.txtwird sie schnell gefunden. Das ist also eine triviale Endlosschleife.

Und so umgehen Sie es: `find -type f! -name messageids.txt -exec grep -Fi "message-id:" {} \; > messageids.txt` Daniel Beck vor 12 Jahren 0
Ich verstehe, dass das ist, was passiert, aber ich verstehe nicht, warum es passiert. Natürlich ist mein Verständnis von find oder grep oder redirects nicht perfekt, aber ich bin mir nicht sicher, welche mich überrascht hat. Also hoffte ich auf eine detaillierte Erklärung des gesamten Befehls. Könnten Sie ein bisschen weiter ausführen? Hammer Bro. vor 12 Jahren 0
@HammerBro. Die Ausgabe muss irgendwo gespeichert werden. RAM ist teuer und temporäre Dateien sind nicht erforderlich, wenn Sie trotzdem nur in die Datei schreiben. Wenn Sie es nicht aktiv verhindern, sofort zu schreiben, geschieht dies einfach. Warum sollte es nicht so sein? Es wird auch sofort auf das Terminal geschrieben, wenn Sie die Ausgabe nicht umleiten. Daniel Beck vor 12 Jahren 1
@DanielBeck "Warum nicht?" Das ist ein guter Punkt. Ich bin immer noch nicht sicher, warum meine Intuitionen in dieser Sache so verwirrt sind. Ich denke, ich mische Rohre mit Weiterleitungen auf einer bestimmten Ebene. Aber das sollte die Sache gut genug ruhen lassen. Danke für das hilfreiche Kommentieren. Hammer Bro. vor 12 Jahren 0
0
Rob

Ich habe gerade so etwas getestet und es hat funktioniert.

for f in $(find . -type f); do grep -Fi "message-id:" $f > messageids.txt; done

Es hängt wahrscheinlich davon ab, ob die Ausgabe zwischengespeichert wurde und wie schnell die Ausgabedatei in der Schleife angezeigt wird. Daniel Beck vor 12 Jahren 0
Ich bin nicht darauf aus, wie Sie das Problem umgehen können. Ich kann die Suchposition oder den Ausgabeort auf verschiedene Arten ändern. Ich suche nach einer einfachen Erklärung, warum dies als Endlosschleife aufgegriffen wird. Ich werde die Frage mit mehr Details aktualisieren. Hammer Bro. vor 12 Jahren 0