Jak stwierdził @samiam , lista jest zwracana w pół losowej kolejności za pośrednictwem readdir()
. Dodam tylko następujące.
Zwrócona lista jest tym, co nazwałbym porządkiem katalogu. W starszych systemach plików kolejność często polega na kolejności dodawania wpisów plików w tabeli katalogu. Jest oczywiście zastrzeżenie, że po usunięciu wpisu w katalogu, wpis ten jest następnie przetwarzany, więc wszelkie kolejne przechowywane pliki zastąpią poprzedni wpis, więc kolejność nie będzie już oparta wyłącznie na czasie tworzenia.
W nowoczesnych systemach plików, w których struktury danych katalogów są oparte na drzewie wyszukiwania lub tabeli mieszającej, kolejność jest praktycznie nieprzewidywalna.
Przykłady
Grzebanie w plikach utworzonych po uruchomieniu polecenia dotykowego ujawnia, że przypisano następujące i-węzły.
$ 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
Widzimy więc, że rozwinięcie nawiasów używane przez dotyk tworzy nazwy plików w kolejności alfabetycznej, więc przypisane są do nich kolejne numery i-węzłów po zapisaniu na HDD. (Nie wpływa to jednak na kolejność w katalogu.)
Uruchamiając tar
komendę wielokrotnie wydaje się wskazywać, że istnieje kolejność na liście, ponieważ działa on wiele razy daje tej samej listy za każdym razem. Tutaj uruchomiłem go 100 razy, a następnie porównałem przebiegi i wszystkie są identyczne.
$ 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
$
Jeśli strategicznie usuniemy powiedzmy, dir/e
a następnie dodamy nowy plik dir/ee
, możemy zobaczyć, że ten nowy plik zajął miejsce, które dir/e
zajmowało wcześniej w tabeli wpisów katalogów.
$ rm dir/e
$ touch dir/ee
Teraz zachowajmy wynik z jednej z for
powyższych pętli, tylko z pierwszej.
$ mv run1 r1A
Teraz, jeśli ponownie uruchomimy for
pętlę, która uruchomi tar
komendę 100 razy, i porównamy ten drugi przebieg z poprzednim:
$ 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
...
Zauważamy, że dir/ee
zajęło dir/e
to miejsce w tabeli katalogów.
stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
ls -f
lubls -U
orfind -maxdepth 1
-f
flaga pochodzi ze starożytnego Uniksa. Miał być szybki. Wyłączyło sortowanie, pomijanie plików dot i kilka innych rzeczy.-U
Flaga jest innowacja GNU który pozwala na wyłączenie sortowania bez żadnych innych skutków ubocznych.readdir()
gruntownie. Kiedy tar dowie się, jakie pliki znajdują się w katalogu, bezpośrednio pyta jądro o listę plików,opendir()
a następniereaddir()
.readdir()
nie zwraca plików w określonej kolejności; sposób uporządkowania plików zależy od systemu plików używanego przez jądro Linuksa.Tam niestety nie ma opcji
tar
sortowania plików w podkatalogach (dodanie jednego pozostaje ćwiczeniem dla czytelnika).źródło
f_op->iterate
Wywołanie, do którego glibcreaddir()
ostatecznie odfiltrowuje via,getdents()
jest odwzorowane na implementację specyficzną dla systemu plików. Nie widzę niczego na wyższym poziomie, który zmieniłbydirent
zwroty implementacji fs.