$ 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コマンドを実行したときに作成されたファイルを突くと、次の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
は、ディレクトリテーブル内の場所です。
readdir()
基本的に。 tarは、ディレクトリにあるファイルを見つけると、opendir()
の後にreaddir()
を付けて、カーネルに直接ファイルリストを要求します。 readdir()
は、特定の順序でファイルを返しません。ファイルの順序は、Linuxカーネルが使用しているファイルシステムによって異なります。
悲しいかな、サブディレクトリでファイルを並べ替えるtar
のオプションはありません(1つを追加することは、読者のための演習として残します)。