tar 在文件上工作的顺序是如何确定的?

Joh*_*ohn 20 linux tar gnu coreutils

$ 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
Run Code Online (Sandbox Code Playgroud)

我原以为它是按字母顺序排列的。但显然不是。这里的公式是什么?

slm*_*slm 18

正如@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
Run Code Online (Sandbox Code Playgroud)

所以我们可以看到 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
$ 
Run Code Online (Sandbox Code Playgroud)

如果我们策略性地删除 saydir/e然后添加一个新文件,dir/ee我们可以看到这个新文件已经取代了dir/e之前在目录条目表中占据的位置。

$ rm dir/e
$ touch dir/ee
Run Code Online (Sandbox Code Playgroud)

现在让我们保留for上面循环之一的输出,只是第一个。

$ mv run1 r1A
Run Code Online (Sandbox Code Playgroud)

现在,如果我们重新运行for将tar再次运行命令 100 次的循环,并将第二次运行与前一次运行进行比较:

$ 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
...
Run Code Online (Sandbox Code Playgroud)

我们注意到dir/ee已经dir/e在目录表中占据了位置。

  • @John `ls -f` 或 `ls -U` 或 `find -maxdepth 1` (3认同)
  • 我认为它依赖于文件系统。我可以想象一个 btree 类型的文件系统根据文件哈希的顺序或类似的顺序对它们进行排序(我有一种感觉,旧的 ReiserFS 对它们的排序方式不同,因为该文件系统动态创建 inode) (2认同)

sam*_*iam 8

readdir()基本上。当 tar 找出目录中的文件时,它会直接通过opendir()后跟readdir(). readdir()不以任何特定顺序返回文件;文件的排序方式取决于 Linux 内核使用的文件系统。

唉,这不是tar对子目录中的文件进行排序的选项(添加一个留给读者作为练习)。