Was passiert, wenn Dateien mitten in einer „for f in *“-SH-Schleife hinzugefügt/entfernt werden?

Was passiert, wenn Dateien mitten in einer „for f in *“-SH-Schleife hinzugefügt/entfernt werden?

Ich habe online ein Beispiel für eine For-Schleife gefunden. Jetzt möchte ich es in meinem Code verwenden, bin mir aber nicht sicher, wie diese Schleife funktioniert

for entry in "$search_dir"/* 
do
  echo "$entry"
done

Jetzt möchte ich fragen

  1. Durchsucht es bei jeder Iteration das Suchverzeichnis und kopiert es bei jeder Iteration Dateien im Suchverzeichnis in die Eintragsvariable „eine Datei“?
  2. Oder mache ich einen Snapshot des gesamten Inhalts von search_dir und speichere diesen Snapshot dann in der Eintragsvariable?
  3. Ändert sich die Ausgabe, wenn jemand eine Datei in „search_dir“ einfügt, während die Schleife noch läuft?

Antwort1

Wenn die Shell zur for-Anweisung gelangt, wird sie den Wert von erweitern $search_dirund das Dateinamen-Globbing durchführen, um eine Liste von Verzeichniseinträgen zu generieren, die durchlaufen werden. Dies geschieht nur einmal, und wenn die Dinge in $search_dirverschwinden oder wenn während der Ausführung der Schleife neue Dateien/Verzeichnisse zu diesem Verzeichnis hinzugefügt werden, werden diese Änderungen nicht übernommen.

Wenn die Schleife auf die Verzeichniseinträge angewendet wird, deren Namen in enthalten sind $entry, möchte man unter Umständen prüfen, ob diese in der Schleife vorhanden sind. Dies gilt insbesondere, wenn bekannt ist, dass die Ausführung der Schleife lange dauert und viele Dateien aus dem einen oder anderen Grund in ständigem Fluss sind:

for entry in "$search_dir"/*; do
    if [ -e "$entry" ]; then
        # operate on "$entry"
    else
        # handle the case that "$entry" went away
    fi
done

Wie Stéphane in seinen Kommentaren zu Recht anmerkt, handelt es sich dabei um einen überflüssigen Test inam meistenFälle.

Antwort2

Die Shell bestimmt die Liste der Werte, die durchlaufen werden sollen, bevor sie mit der Ausführung des Schleifenkörpers beginnt. Das heißt:

  1. Die Shell erstellt einen Pfad unter Verwendung des Werts der Variablen search_dir.
  2. Die Shell sammelt die Liste der Dateinamen im angegebenen Verzeichnis, um die Liste der Übereinstimmungen für das Platzhaltermuster zu erstellen.
  3. Die Shell führt den Schleifenkörper nacheinander mit jedem Element der Übereinstimmungsliste aus.

Sie können den Wert der Variablen search_dirund den Inhalt des Verzeichnisses ändern, während die Schleife ausgeführt wird. Dies hat keinen Einfluss darauf, auf welche Dateien die Schleife einwirkt.

Wenn eine Datei entfernt wird, während die Schleife andere Dateien verarbeitet, dann existiert diese Datei nicht mehr, sobald sie zu dieser Datei gelangt. Je nachdem, was Sie in der Schleife tun, kann das eine Rolle spielen oder auch nicht. Wenn es einen parallelen Prozess gibt, der Dateien entfernen kann, beachten Sie, dass das Testen, ob die Datei existiert, bevor sie verarbeitet wird, dieses Problem nicht wirklich löst, daDie Datei könnte zwischen dem Testzeitpunkt und dem Beginn der Verarbeitung entfernt werden.

Wenn Sie eine Datei als verarbeitet markieren müssen, um sicherzustellen, dass Sie sie nicht zweimal verarbeiten, sollte dieses Skript die Dateien nach der Verarbeitung in ein anderes Verzeichnis verschieben. Das Verschieben einer Datei in ein anderes Verzeichnis (auf demselben Dateisystem) istatomar: entweder ist es noch nicht fertig oder es ist fertig, es gibt keinen Zwischenzustand. Aber noch einmal, wenn einandersProzess (möglicherweise eine andere Instanz dieses Skripts) Dateien verschiebt, dann stößt die Schleife manchmal auf Dateien, die während der Ausführung der Schleife verschoben werden.

Wenn Sie neue Dateien verarbeiten möchten, während sie erstellt werden, müssen Sie die Schleife erneut ausführen. Natürlich könnten während der Ausführung der Schleife oder nachdem alle vorherigen Dateien verarbeitet wurden, Dateien erstellt werden, sodass das Skript für immer weiterlaufen müsste. Es gibt Tools, die warten, bis eine Datei in einem Verzeichnis erstellt wird. Unter Linux ist die grundlegende Funktion dafürinoffiziell; wenn Sie Dateien verarbeiten müssen, während sie erstellt werden, danninotifywaitoderinkronsollte Ihnen helfen. Denken Sie daran, dass inotify Sie nur über erstellte (oder geänderte oder aufgerufene) Dateien benachrichtigt, je nach Auslöser.nachdie auf inotify basierenden Befehle starten; Sie müssen sich auch um zuvor vorhandene Dateien kümmern, und das können Sie nicht einfach tun, for entry in *; do …; done; inotifywait …da während der Ausführung der Schleife oder sogar während des inotifywaitStartens des Befehls Dateien erstellt werden können.

verwandte Informationen