如何获得空的 tar 存档?

Sea*_*der 32 tar

我正在制作一个 RPM,其中所有内容都包含在 .spec 文件中(不要问:-)。rpmbuild 需要一个“源”文件,所以我试图创建一个空的 tar 文件。但是,如果我不提供任何文件名,tar 会抱怨:

tar: Cowardly refusing to create an empty archive
Try `tar --help' or `tar --usage' for more information.
Run Code Online (Sandbox Code Playgroud)

如何创建一个真正空的 tar 文件?

Sea*_*der 32

您可以强制 GNU 和 BSD tar 创建一个空的存档:

tar -cf tarfilename.tar -T /dev/null
Run Code Online (Sandbox Code Playgroud)

  • @dpk:如果我明白你在说什么,你为什么不总是使用 append ?如果 tar 文件不存在,则追加将创建它,因此您无需检查它是否是第一个文件,只需追加,如果它是第一个文件,则 tar 将创建它。 (4认同)
  • 创建空 tar 的原因之一:脚本化 tar 创建。步骤 1:创建 tar.gz 文件。第二步:一一添加文件。您可以使用“如果是第一个文件,则创建其他文件,然后追加”来完成此操作,但这并不那么顺利。 (2认同)

jos*_*sch 11

如果你有 GNU tar

要么使用 /dev/null

$ tar -cf empty.tar --files-from /dev/null
Run Code Online (Sandbox Code Playgroud)

或者通过从标准输入读取 EOF。

$ printf '' | tar -cf empty.tar --files-from -
Run Code Online (Sandbox Code Playgroud)

如果你没有焦油

空的 tar 文件只是一个包含 10240 个 NUL 字节的文件。因此,要创建一个空的 tar 文件,您甚至不需要tar,而是可以使用以下任一方法:

$ head --bytes=10240 /dev/zero > empty.tar
$ truncate --size=10240 empty.tar
$ fallocate --length=10240 empty.tar
$ dd if=/dev/zero bs=10240 count=1 iflag=fullblock > empty.tar
$ dd if=/dev/zero bs=1 count=10240 > empty.tar
Run Code Online (Sandbox Code Playgroud)

为什么这样做?

https://www.gnu.org/software/tar/manual/html_node/Standard.html

在物理上,归档由一系列文件条目组成,这些条目由归档结束条目终止,该条目由两个 512 块的零字节组成。

在存档文件的末尾有两个 512 字节的块,其中填充了二进制零作为文件结束标记。

因此,在实践中,将 1024 个零字节(两倍 512 字节块)写入文件以获得空存档就足够了:

$ head --bytes=1024 /dev/zero > empty.tar
$ tar tvf empty.tar
Run Code Online (Sandbox Code Playgroud)

如果我们只将 1023 个零和一个“1”写入文件,tar 会抱怨,因为它不是两个全零填充的块,它只找到一个全零的块(第一个),而第二个不是全零:

$ { head --bytes=1023 /dev/zero; printf '\001' } > empty.tar
$ tar tvf empty.tar
tar: A lone zero block at 1
Run Code Online (Sandbox Code Playgroud)

但是为什么不只是 1024 个零字节而是 10240 个呢?原因是阻塞或默认记录大小或阻塞因子:

https://www.gnu.org/software/tar/manual/html_section/tar_76.html

默认的分块因子是 20。块大小为 512 字节时,我们得到的记录大小为 10240。并且 tar 将始终填充 tarball,使其大小是记录大小的倍数:

某些设备要求所有写入操作都是特定大小的倍数,因此,tar 将存档填充到下一个记录边界。


小智 9

BSD: tar cvf empty.tar --from-file /dev/null

GNU(Linux): tar cvf empty.tar --files-from /dev/null

索拉里斯: tar cvf empty.tar -I /dev/null