web-dev-qa-db-ja.com

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

私はそれがアルファベット順であることを期待していました。しかし、明らかにそうではありません。ここでの式は何ですか?

17
John

@ samiam が述べたように、リストはreaddir()を介してセミランダムな順序で返されます。以下を追加します。

返されるリストは、私がディレクトリの順序と呼ぶものです。古いファイルシステムでは、順序は多くの場合、ディレクトリのテーブル内のファイルエントリが追加された作成順序です。もちろん、これには注意が必要です。ディレクトリエントリが削除されると、このエントリは再利用されるため、保存されている後続のファイルは以前のエントリを置き換えます。そのため、作成時間のみに基づいた順序ではなくなります。

ディレクトリデータ構造が検索ツリーまたはハッシュテーブルに基づいている現代のファイルシステムでは、実際の順序は予測できません。

Touchコマンドを実行したときに作成されたファイルを突くと、次のiノードが割り当てられていることがわかります。

$ 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に書き込まれるときにそれらに連続したiノード番号が割り当てられることがわかります。 (ただし、ディレクトリ内の順序には影響しません。)

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
$ 

戦略的に削除する場合はdir/eしてから、新しいファイルを追加しますdir/eeこの新しいファイルがdir/eディレクトリエントリテーブルで前に占有されています。

$ rm dir/e
$ touch dir/ee

ここで、上記のforループの1つからの出力を、最初の1つだけ保持します。

$ mv run1 r1A

ここで、forコマンドを再度100回実行するtarループを再実行し、この2回目の実行を前の実行と比較します。

$ 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は、ディレクトリテーブル内の場所です。

16
slm

readdir()基本的に。 tarは、ディレクトリにあるファイルを見つけると、opendir()の後にreaddir()を付けて、カーネルに直接ファイルリストを要求します。 readdir()は、特定の順序でファイルを返しません。ファイルの順序は、Linuxカーネルが使用しているファイルシステムによって異なります。

悲しいかな、サブディレクトリでファイルを並べ替えるtarのオプションはありません(1つを追加することは、読者のための演習として残します)。

8
samiam