在一个命令中连接多个 tar 文件

在一个命令中连接多个 tar 文件

我每天都会收到 4 到 100 个非常大的 tar (~20GB) 存档文件。过去,我一直通过循环遍历文件系统上看到的每个存档并执行类似以下操作来连接它们

/bin/tar -concatenate --file=allTars.tar receivedTar.tar

但问题是,当我连接越来越多的 tar 文件时,它必须读到末尾allTars.tar才能再次开始连接。有时需要 20 多分钟才能开始添加另一个 tar 文件。它太慢了,我错过了约定的完整交付时间allTars.tar

我还尝试向 tar 命令提供如下文件列表:

/bin/tar --concatenate --file=alltars.tar receiverTar1.tar receivedTar2.tar receivedTar3.tar...etc

这给出了非常奇怪的结果。 allTars.tar将是预期的大小(即接近所有文件的大小加在一起)但在解压receivedTar.tar时似乎覆盖了文件。allTars.tar

有没有办法用一个命令连接所有这些 tar 文件,这样它就不必每次都读取到被连接的存档的末尾它们是否已正确解压并包含所有文件/数据?

答案1

这可能对您没有帮助,但是如果您愿意-i在从最终档案中提取时使用该选项,那么您可以简单地cat将 tar 放在一起。tar 文件以一个充满空值的标头结尾,并且直到记录末尾还有更多的空值填充。使用--concatenatetar 必须遍历所有标头以找到最终标头的确切位置,以便从那里开始覆盖。

如果您只使用cattar,则标题之间会有多余的空值。该-i选项要求 tar 忽略标题之间的这些空值。因此您可以

cat  receiverTar1.tar receivedTar2.tar ... >>alltars.tar
tar -itvf alltars.tar

此外,您的tar --concatenate示例应该可以正常工作。但是,如果您在多个 tar 存档中有同名文件,则在从生成的 tar 中提取所有内容时,您将多次重写该文件。

答案2

这个问题相当老了,但我希望自己能更早找到以下信息。因此,如果其他人偶然发现这一点,请尽情享受:

Jeff 上面描述的是 gnu tar 中的一个已知错误(于 2008 年 8 月报告)。只有第一个存档(选项后面的存档-f)的 EOF 标记会被删除。如果您尝试连接 2 个以上的存档,则最后的存档将“隐藏”在文件结束标记后面。

这是 tar 中的一个错误。它会连接整个档案,包括尾随的零块,因此默认情况下,读取结果档案会在第一次连接后停止。

来源:https://lists.gnu.org/archive/html/bug-tar/2008-08/msg00002.html (以及后续消息)

考虑到这个漏洞已经存在很久了,我不知道它是否会被修复。我怀疑受影响的人数是否达到临界水平。

避免此错误的最佳方法可能是使用该-i选项,至少对于文件系统上的 .tar 文件而言。

正如 Jeff 指出的那样,tar --concatenate在连接下一个档案之前,可能需要很长时间才能到达 EOF。因此,如果您要面对需要tar -i解压选项的“损坏”档案,我建议您执行以下操作:

而不是使用 tar --concatenate -f archive1.tar archive2.tar archive3.tar 你最好还是跑吧 cat archive2.tar archive3.tar >> archive1.tar或者管道到,dd如果您打算写入磁带设备。还请注意,这可以如果在将新数据(覆盖)写入磁带之前未将磁带归零,则会导致意外行为。出于这个原因,我将在我的应用程序中采用嵌套 tars 的方法,如问题下方的评论中所建议的那样。

上述建议基于以下非常小的样本基准:

time tar --concatenate -vf buffer.100025.tar buffer.100026.tar
  real  65m33.524s
  user  0m7.324s
  sys   2m50.399s

time cat buffer.100027.tar >> buffer.100028.tar
  real  46m34.101s
  user  0m0.853s
  sys   1m46.133s

buffer.*.tar 文件大小均为 100GB,除了每次调用之外,系统基本处于空闲状态。时间差异非常显著,因此我个人认为尽管样本量很小,但这个基准测试仍然有效,但您可以自行判断,最好在您自己的硬件上运行这样的基准测试。

答案3

正如您所说,在将第二个源存档附加到目标存档文件之前,必须将目标存档文件读到末尾。GNU tar 有一个-n选项,指示它假设文件是​​可寻址的(请记住,tar 是为不可寻址的磁带和流存档设计的)。GNU tar 默认自动检测文件是否可寻址,但是许多用户(例如您)可以通过添加以下选项来确保 tar 跳过读取每个记录的完整内容-n

tar -n --concatenate --file=target_file.tar  other_file.tar

我无法验证(在撰写本文时)哪个版本的 tar(如果有的话)将按预期执行此命令。 如果其他用户有能力证明此解决方案,请在下面发表评论,我会相应地更新此答案。

答案4

由于串联需要大量 I/O,我建议 RAID 0 中必须有 3 个 SSD(1TB)。SATA 3 上的单个 SSD 可提供 500mb/s 的读取速度和类似的写入速度。价格昂贵,但速度快 3 倍。

相关内容