GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was passiert unter Linux, wenn 1000 Dateien in einem Verzeichnis an einen anderen Ort verschoben werden, während weitere 300 Dateien zum Quellverzeichnis hinzugefügt wurden?

Dies hängt davon ab, welche Tools Sie verwenden:Lassen Sie uns einige Fälle überprüfen:

Wenn Sie etwas in der Art von mv /path/to/source/* /path/to/dest/ ausführen Int einer Shell werden am Ende die ursprünglichen 1000 Dateien verschoben, die neuen 300 bleiben unberührt. Dies kommt daher, dass die Shell die * erweitert vor Beginn des Verschiebevorgangs, also wenn der Verschiebevorgang läuft, ist die Liste bereits fixiert.

Wenn Sie Nautilus (und andere GUI-Freunde) verwenden, werden Sie auf die gleiche Weise enden:Es wird die Verschiebeoperation basierend darauf ausführen, welche Dateien ausgewählt wurden - dies ändert sich nicht, wenn neue Dateien angezeigt werden.

Wenn Sie Ihr eigenes Programm verwenden, verwenden Sie Systemaufrufe entlang der Schleifenlinie über glob und nur eine mv bis glob leer bleibt, landen am Ende alle 1300 Dateien im neuen Verzeichnis. Denn jeder neue glob holt die neuen Dateien ab, die in der Zwischenzeit aufgetaucht sind.


Wenn Sie das System anweisen, alle Dateien aus einem Verzeichnis zu verschieben, listet es alle Dateien auf und beginnt dann mit dem Verschieben. Wenn neue Dateien im Verzeichnis erscheinen, werden sie nicht zur Liste der zu verschiebenden Dateien hinzugefügt, sodass sie am ursprünglichen Speicherort verbleiben.

Sie können natürlich eine andere Methode zum Verschieben von Dateien als mv programmieren die regelmäßig nach neuen Dateien im Quellverzeichnis sucht.


Der Kernel selbst kann nicht "in der Mitte" einer Operation "1000 Dateien verschieben" sein. Sie müssen viel genauer angeben, welche Operation Sie vorschlagen.

Ein Thread kann mit dem rename(*oldpath, const char *newpath) nur jeweils eine Datei verschieben oder renameat Systemaufrufe (und nur innerhalb desselben Dateisystems). Oder Linux renameat2 die Flags wie RENAME_EXCHANGE hat um zwei Pfadnamen atomar auszutauschen, oder RENAME_NOREPLACE zu nicht Ersetzen Sie das Ziel, falls vorhanden. (z.B. Erlauben eines mv -i Implementierung, die die Racebedingung von stat vermeidet und dann rename , was immer noch eine nach stat erstellte Datei überschreiben würde .link + unlink könnte das auch lösen, denn link schlägt fehl, wenn der neue Name existiert.)

Aber jeder dieser Systemaufrufe benennt nur einen einzigen Verzeichniseintrag pro Systemaufruf um . Mit POSIX renameat mit olddirfd und newdirfd (geöffnet mit open(O_DIRECTORY) ) würde es Ihnen ermöglichen, Dateien in einem Verzeichnis zu durchlaufen, selbst wenn das Quell- oder Zielverzeichnis selbst umbenannt worden war. (Die Verwendung relativer Pfade könnte dies auch mit regulärem rename() ermöglichen .)

Wie auch immer, wie die anderen Antworten sagen, werden die meisten Programme, die den Rename-Systemaufruf verwenden, eine Liste von Dateinamen ermitteln, bevor sie den ersten rename ausführen . (Normalerweise mit readdir(3) Die POSIX-Bibliothek fungiert als Wrapper für plattformspezifische Systemaufrufe wie Linux getdents ).

Aber wenn Sie von find -exec ... {} \; sprechen um einen Befehl pro Datei auszuführen, oder das effizientere -exec {} + Bei so vielen Dateien, dass sie nicht auf eine Befehlszeile passen, können Sie sicherlich Umbenennungen vornehmen, während Sie noch scannen. z. B.

find . -name '*.txt' -exec mv -t ../txtfiles {} \;   # Intentionally inefficient

Wenn Sie einen neuen .txt erstellt haben Dateien, während dies ausgeführt wurde, möglicherweise siehe einige davon in ../txtfiles . Aber intern find(1) wird open(O_DIRECTORY) verwendet haben und getdents auf . .

Wenn ein Systemaufruf ausreichen würde, um alle zurückzugeben die Verzeichniseinträge in . (wobei find nacheinander eine Schleife durchläuft und nur dann weitere Systemaufrufe durchführt, wenn dies für -type erforderlich ist oder rekursiv oder fork+exec bei einer Übereinstimmung), dann ist die Liste eine Momentaufnahme der Verzeichniseinträge zu einem bestimmten Zeitpunkt. Weitere Änderungen am Verzeichnis können sich nicht auf find auswirken tut, weil es bereits eine Kopie des Verzeichnisses hat, das auflistet, was es durchlaufen wird. (Wahrscheinlich verwendet es intern readdir(3) , das einen Eintrag nach dem anderen zurückgibt, aber innerhalb von glibc kennen wir es von der Verwendung von strace find . dass es einen getdents64 macht Systemaufruf mit einer Puffergröße von count=32768 Einträge.)

Aber wenn das Verzeichnis riesig ist und/oder der Kernel find nicht füllt 's-Puffer, muss es einen zweiten getdents-Systemaufruf machen, nachdem es das, was es beim ersten Mal bekommen hat, durchlaufen hat. So könnte es vielleicht neue Einträge sehen, nachdem es einige Umbenennungen vorgenommen hat.

Aber siehe Diskussion in den Kommentaren unter anderen Antworten:Der Kernel hat möglicherweise einen Snapshot für uns erstellt, da getdents (glaube ich) nicht zweimal denselben Dateinamen zurückgeben darf. Unterschiedliche Dateisysteme verwenden unterschiedliche Sortier-/Indizierungsmechanismen, um den Zugriff auf einen Eintrag in einem riesigen Verzeichnis effizienter zu gestalten als eine lineare Suche. Das Hinzufügen oder Entfernen eines Verzeichnisses kann also möglicherweise andere Auswirkungen auf die Reihenfolge der verbleibenden Einträge haben. Hmm, wahrscheinlich ist es wahrscheinlicher, dass Dateisysteme eine stabile Ordnung beibehalten und nur einen aktuellen Index aktualisieren (wie den EXT4 dir_index Feature), so dass die Position eines Verzeichnis-FDs nur ein Verzeichniseintrag sein kann, von dem aus fortgefahren werden kann? Ich weiß wirklich nicht, wie der telldir(3) Bibliotheksschnittstelle wird auf lseek abgebildet , oder wenn dies nur eine Sache des Benutzerraums ist, um den vom Benutzerraum erhaltenen Puffer zu durchlaufen. Aber mehrfach getdents kann erforderlich sein, um alle Einträge aus einem riesigen Verzeichnis zu erhalten, also muss der Kernel in der Lage sein, eine aktuelle Position aufzuzeichnen, selbst wenn das Suchen nicht unterstützt wird.

Fußnote 1:

Um sich zwischen Dateisystemen zu "bewegen", muss der Benutzerbereich kopieren und die Verknüpfung aufheben. (z.B. mit open und entweder read+write , mmap+write oder sendfile(2) oder copy_file_range(2) , die beiden letzteren vermeiden es vollständig, die Dateidaten durch den Benutzerbereich zu senden.)


Linux
  1. Was sind Sparse-Dateien in Linux?

  2. Was sind die Unterschiede zwischen lsof und netstat unter Linux?

  3. Was sind die Unterschiede zwischen Linux- und Windows-.txt-Dateien (Unicode-Codierung)

  4. Was ist der schnellste Weg, um unter Linux eine Million Bilder von einem Verzeichnis in ein anderes zu verschieben?

  5. Was ist das Äquivalent von Active Directory unter Linux

Verwenden Sie das Linux-Terminal, um zu sehen, welche Dateien sich auf Ihrem Computer befinden

Linux – Was sind die verschiedenen Möglichkeiten zum Festlegen von Dateiberechtigungen usw. unter Gnu/Linux?

Absoluter vs. relativer Pfad in Linux:Was ist der Unterschied?

Was sind die verschiedenen Möglichkeiten zum Festlegen von Dateiberechtigungen usw. unter gnu/linux

Linux-Dateihierarchie - was ist der beste Ort zum Speichern von Sperrdateien?

Was bedeutet das Suffix .d unter Linux?