Wie @samiam angegeben hat, wird die Liste in einer halbzufälligen Reihenfolge über an Sie zurückgesendet readdir()
. Ich füge nur Folgendes hinzu.
Die zurückgegebene Liste würde ich als Verzeichnisreihenfolge bezeichnen. Bei älteren Dateisystemen entspricht die Reihenfolge oft der Erstellungsreihenfolge, in der die Dateieinträge in der Tabelle des Verzeichnisses hinzugefügt wurden. Dies hat natürlich eine Einschränkung: Wenn ein Verzeichniseintrag gelöscht wird, wird dieser Eintrag wiederverwendet, sodass alle nachfolgenden Dateien, die gespeichert werden, den vorherigen Eintrag ersetzen, sodass die Reihenfolge nicht mehr ausschließlich auf der Erstellungszeit basiert.
In modernen Dateisystemen, in denen Verzeichnisdatenstrukturen auf einem Suchbaum oder einer Hash-Tabelle basieren, ist die Reihenfolge praktisch unvorhersehbar.
Beispiele
Das Stöbern in den Dateien, die beim Ausführen Ihres Touch-Befehls erstellt wurden, zeigt, dass die folgenden Inodes zugewiesen wurden.
$ touch dir/{{1..8},{a..p}}
$ stat --printf="%n -- %i\n" dir/*
dir/1 -- 10883235
dir/2 -- 10883236
dir/3 -- 10883242
dir/4 -- 10883243
dir/5 -- 10883244
dir/6 -- 10883245
dir/7 -- 10883246
dir/8 -- 10883247
dir/a -- 10883248
dir/b -- 10883249
dir/c -- 10883250
dir/d -- 10883251
dir/e -- 10883252
dir/f -- 10883253
dir/g -- 10883254
dir/h -- 10883255
dir/i -- 10883256
dir/j -- 10883299
dir/k -- 10883302
dir/l -- 10883303
dir/m -- 10883311
dir/n -- 10883424
dir/o -- 10883426
dir/p -- 10883427
So können wir sehen, dass die von touch verwendete geschweifte Klammer die Dateinamen in alphabetischer Reihenfolge erstellt und ihnen beim Schreiben auf die Festplatte fortlaufende Inode-Nummern zugewiesen werden. (Dies hat jedoch keinen Einfluss auf die Reihenfolge im Verzeichnis.)
Wenn Sie Ihren tar
Befehl mehrmals ausführen, scheint dies darauf hinzudeuten, dass die Liste eine Reihenfolge aufweist, da die mehrfache Ausführung jedes Mal dieselbe Liste ergibt. Hier habe ich es 100 Mal ausgeführt und dann die Läufe verglichen und sie sind alle identisch.
$ for i in {1..100};do tar cJvf file.tar.xz dir/ > run${i};done
$ for i in {1..100};do cmp run1 run${i};done
$
Wenn wir beispielsweise strategisch löschen dir/e
und dann eine neue Datei hinzufügen, dir/ee
können wir sehen, dass diese neue Datei den Platz dir/e
eingenommen hat, den sie zuvor in der Verzeichniseintragstabelle eingenommen hat.
$ rm dir/e
$ touch dir/ee
Lassen Sie uns nun die Ausgabe von einer der for
obigen Schleifen, nur der ersten , behalten .
$ mv run1 r1A
Wenn wir nun die for
Schleife, die den tar
Befehl 100 Mal ausführt, erneut ausführen und diesen zweiten Lauf mit dem vorherigen vergleichen:
$ sdiff r1A run1
dir/ dir/
...
dir/c dir/c
dir/f dir/f
dir/e | dir/ee
dir/o dir/o
dir/2 dir/2
...
Wir stellen fest, dass dies in der Verzeichnistabelle dir/ee
stattgefunden hat dir/e
.
stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
ls -f
orls -U
orfind -maxdepth 1
-f
Flagge stammt aus dem alten Unix. Sein Zweck war es, schnell zu sein. Es deaktivierte das Sortieren, das Überspringen von Punktedateien und ein paar andere Dinge. Die-U
Flagge ist eine GNU-Innovation, mit der Sie die Sortierung ohne weitere Nebenwirkungen deaktivieren können.readdir()
Grundsätzlich. Wenn tar herausfindet, welche Dateien sich in einem Verzeichnis befinden, fragt er den Kernel direkt nach einer Dateiliste überopendir()
gefolgt vonreaddir()
.readdir()
gibt die Dateien nicht in einer bestimmten Reihenfolge zurück; Die Reihenfolge der Dateien hängt vom Dateisystem ab, das vom Linux-Kernel verwendet wird.Leider ist dies keine Option
tar
, um Dateien in Unterverzeichnissen zu sortieren (das Hinzufügen einer Option wird dem Leser als Übung überlassen).quelle
f_op->iterate
Aufruf, den glibcreaddir()
schließlich nach via filtert,getdents()
wird einer dateisystemspezifischen Implementierung zugeordnet. Ich kann auf einer höheren Ebene nichts sehen, was die Ergebnisse derdirent
Implementierung von fs neu ordnet .