ファイルでtarが機能する順序はどのように決定されますか?


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

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

回答:


14

以下のよう@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
$ 

sayを戦略的に削除してdir/eから新しいファイルdir/eeを追加すると、この新しいファイルがdir/eディレクトリエントリテーブルで以前占有していた場所を取っていることがわかります。

$ rm dir/e
$ touch dir/ee

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

$ mv run1 r1A

次に、再実行すると fortarコマンドを再度100回ループ実行し、この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ます。


うわー、これは本当に素晴らしい答えです。ディレクトリを指定すると、tarがそのサブアイテムを処理する順序を確認する方法はありますか?私はそれについて本当に自信がありませんが、以下はあなたにどのように見えますか?stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
ジョン14年

2
ファイルシステムに依存していると思います。私は、ファイルのハッシュまたはそのようないくつか(そのファイルシステムが動的にiノードを作成するので、私は、違った意味に古いReiserFSの受注それらを持っている)の順序に基づいてそれらをソートBTREE型ファイルシステムを想像することができます
samiam

1
@samiam-正しい、この回答は「ディレクトリの順序」が「ディレクトリのテーブル内のファイルエントリが追加された作成順序」であると主張しており、それ自体がtarファイルの内容の断片を示して、これが正しくないことを示しています。現在のLinux ext *ファイルシステムを含む多くのファイルシステムは、いくつかの古いファイルシステムのような単純なシーケンシャルテーブルではなく、ディレクトリ構造でツリーやハッシュを使用します。
ミチャウポリトウスキ14年

3
@John ls -fまたはls -Uまたはfind -maxdepth 1

1
@John the -fflagは古代のUnixから来ています。その目的は高速であることでした。ソート、ドットファイルのスキップ、その他いくつかのことを無効にしました。この-Uフラグは、他の副作用なしにソートを無効にできるGNUの革新です。

8

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

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


1
iノードの値に基づいてそれらを取得するかどうか疑問に思っていましたか?
slm

1
@slm f_op->iterateglibcがreaddir()最終的にviaにフィルタリングする呼び出しgetdents()は、ファイルシステム固有の実装にマッピングされます。私direntはfs実装が返すs を並べ替えるより高いレベルでは何も見ることができません。
マット14年

@slmいいえ、inodeの値がディレクトリの順序に影響するファイルシステムについて聞いたことがありません。
ジル 'SO-悪であるのをやめる' 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.