Jak określa się kolejność, w jakiej tar działa na plikach?

15
$ touch dir/{{1..8},{a..p}}
$ tar cJvf file.tar.xz dir/
dir/
dir/o
dir/k
dir/b
dir/3
dir/1
dir/i
dir/7
dir/4
dir/e
dir/a
dir/g
dir/2
dir/d
dir/5
dir/8
dir/c
dir/n
dir/f
dir/h
dir/6
dir/l
dir/m
dir/j
dir/p

Spodziewałbym się, że będzie to alfabetycznie. Ale najwyraźniej tak nie jest. Jaka jest formuła tutaj?

Jan
źródło

Odpowiedzi:

14

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 tarkomendę 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/ea następnie dodamy nowy plik dir/ee, możemy zobaczyć, że ten nowy plik zajął miejsce, które dir/ezajmowało wcześniej w tabeli wpisów katalogów.

$ rm dir/e
$ touch dir/ee

Teraz zachowajmy wynik z jednej z forpowyższych pętli, tylko z pierwszej.

$ mv run1 r1A

Teraz, jeśli ponownie uruchomimy forpętlę, która uruchomi tarkomendę 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/eezajęło dir/eto miejsce w tabeli katalogów.

slm
źródło
Wow, to naprawdę świetna odpowiedź. Biorąc pod uwagę katalog, czy mogę w jakiś sposób sprawdzić, w jakiej kolejności tar będzie przetwarzać swoje podelementy? Nie jestem tego do końca pewny, ale jak ci się podoba? stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
John
2
Myślę, że to zależy od systemu plików. Mogę sobie wyobrazić system plików typu btree sortujący je na podstawie kolejności skrótów plików lub czegoś
podobnego
1
@samiam - prawda, ta odpowiedź twierdzi, że „kolejność katalogów” to „kolejność tworzenia, do której dodano wpisy plików w tabeli katalogu”, a następnie sama pokazuje fragmenty zawartości pliku tar pokazujące, że to nieprawda. Wiele systemów plików, w tym obecne systemy plików ext * Linux, używają drzew i / lub skrótów w swoich strukturach katalogów, a nie prostych tabel sekwencyjnych, takich jak niektóre starsze systemy plików.
Michał Politowski
3
@John ls -flub ls -Uorfind -maxdepth 1
1
@John -fflaga pochodzi ze starożytnego Uniksa. Miał być szybki. Wyłączyło sortowanie, pomijanie plików dot i kilka innych rzeczy. -UFlaga jest innowacja GNU który pozwala na wyłączenie sortowania bez żadnych innych skutków ubocznych.
8

readdir()gruntownie. Kiedy tar dowie się, jakie pliki znajdują się w katalogu, bezpośrednio pyta jądro o listę plików, opendir()a następnie readdir(). 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 tarsortowania plików w podkatalogach (dodanie jednego pozostaje ćwiczeniem dla czytelnika).

Samiam
źródło
1
Zastanawiałem się, czy pobiera je na podstawie wartości ich i-węzła?
slm
1
@slm f_op->iterateWywołanie, do którego glibc readdir()ostatecznie odfiltrowuje via, getdents()jest odwzorowane na implementację specyficzną dla systemu plików. Nie widzę niczego na wyższym poziomie, który zmieniłby direntzwroty implementacji fs.
Matt
@slm Nie, nigdy nie słyszałem o systemie plików, w którym wartość i-węzła miałaby wpływ na kolejność katalogów.
Gilles „SO- przestań być zły”