Comme @samiam l' a déclaré, la liste vous est retournée dans un ordre semi-aléatoire via readdir()
. Je vais juste ajouter ce qui suit.
La liste renvoyée est ce que j'appellerais l'ordre du répertoire. Sur les anciens systèmes de fichiers, l'ordre est souvent l'ordre de création auquel les entrées de fichier dans la table du répertoire ont été ajoutées. Il y a bien sûr une mise en garde à cela, lorsqu'une entrée de répertoire est supprimée, cette entrée est ensuite recyclée, de sorte que tous les fichiers suivants qui sont stockés remplaceront l'entrée précédente, de sorte que l'ordre ne sera plus basé uniquement sur le temps de création.
Sur les systèmes de fichiers modernes où les structures de données de répertoire sont basées sur une arborescence de recherche ou une table de hachage, l'ordre est pratiquement imprévisible.
Exemples
Piquer les fichiers créés lorsque vous exécutez votre commande tactile révèle que les inodes suivants ont été attribués.
$ 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
Ainsi, nous pouvons voir que l'expansion de l'accolade utilisée par le toucher crée les noms de fichiers par ordre alphabétique et donc des numéros d'inode séquentiels leur sont attribués lorsqu'ils sont écrits sur le disque dur. (Cela n'influence cependant pas l'ordre dans le répertoire.)
L'exécution de votre tar
commande plusieurs fois semble indiquer qu'il existe un ordre dans la liste, car son exécution multiple génère la même liste à chaque fois. Ici, je l'ai couru 100 fois, puis j'ai comparé les courses et elles sont toutes identiques.
$ 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
$
Si nous supprimons stratégiquement say dir/e
puis ajoutons un nouveau fichier, dir/ee
nous pouvons voir que ce nouveau fichier a pris la place qui dir/e
occupait auparavant dans le tableau des entrées des répertoires.
$ rm dir/e
$ touch dir/ee
Maintenant, gardons la sortie de l'une des for
boucles ci-dessus, juste la 1ère.
$ mv run1 r1A
Maintenant, si nous réexécutons la for
boucle qui exécutera à nouveau la tar
commande 100 fois, et comparons cette deuxième exécution avec la précédente:
$ 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
...
On remarque que cela dir/ee
a pris dir/e
place dans la table des répertoires.
stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
ls -f
orls -U
orfind -maxdepth 1
-f
drapeau vient de l'ancien Unix. Son but était d'être rapide. Il a désactivé le tri, l'omission des fichiers dot et quelques autres choses. Le-U
drapeau est une innovation GNU qui vous permet de désactiver le tri sans aucun autre effet secondaire.readdir()
fondamentalement. Lorsque tar découvre quels fichiers se trouvent dans un répertoire, il demande directement au noyau une liste de fichiers viaopendir()
suivi dereaddir()
.readdir()
ne renvoie pas les fichiers dans un ordre particulier; la façon dont les fichiers sont ordonnés dépend du système de fichiers utilisé par le noyau Linux.Là, hélas, il n'y a pas d'option pour
tar
trier les fichiers dans les sous-répertoires (en ajouter un est laissé comme exercice pour le lecteur).la source
f_op->iterate
appel que la glibcreaddir()
finit par filtrer vers viagetdents()
est mappé sur une implémentation spécifique au système de fichiers. Je ne vois rien à un niveau supérieur qui réorganise ledirent
retour de l'implémentation fs.