Linux
tar 處理文件的順序是如何確定的?
$ 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
我本來希望它是按字母順序排列的。但顯然不是。公式是什麼,這裡?
正如@samiam所說,該列表以半隨機順序通過
readdir()
. 我將添加以下內容。返回的列表就是我所說的目錄順序。在較舊的文件系統上,順序通常是添加目錄表中的文件條目的創建順序。當然有一個警告,當一個目錄條目被刪除時,這個條目會被回收,所以任何後續儲存的文件都將替換之前的條目,因此順序將不再僅僅基於創建時間。
在目錄資料結構基於搜尋樹或雜湊表的現代文件系統上,順序實際上是不可預測的。
例子
查看執行 touch 命令時創建的文件會發現已分配以下 inode。
$ 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
所以我們可以看到 touch 使用的大括號擴展按字母順序創建文件名,因此在寫入 HDD 時它們被分配了連續的 inode 編號。(但這不會影響目錄中的順序。)
多次執行您的
tar
命令似乎表明該列表有一個順序,因為多次執行它每次都會產生相同的列表。在這裡,我執行了 100 次,然後比較了執行,它們都是相同的。$ 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 $
如果我們策略性地刪除 say
dir/e
然後添加一個新文件dir/ee
,我們可以看到這個新文件已經dir/e
佔據了目錄條目表中先前佔據的位置。$ rm dir/e $ touch dir/ee
現在讓我們保留上述
for
循環之一的輸出,即第一個循環。$ mv run1 r1A
現在,如果我們重新執行將再次執行命令 100 次的
for
循環,並將第二次執行與前一次執行進行比較:tar
$ 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 ...
我們注意到’ 在目錄表中的位置
dir/ee
。dir/e