我有一个二进制文件(我们称之为displayFiles
),它将同时获取多个 tar 文件并将 tar 文件打印到 stdout。然后我将 stdout 传输到tar
。
当二进制文件仅下载单个 tar 时,此方法可行。如果我一次获取多个 tar 并将它们通过管道传输到,tar
此方法可行吗?displayFiles
程序不会在一个文件和下一个文件之间暂停。
例如:
./displayFiles | { tar -xvf -; }
答案1
tar 档案的结尾由两个连续的零填充的 512 字节记录标记。从 stdin 读取时,tar
应在读取两个零填充的记录后停止,以便下一个工具可以读取后面的数据(如果有)。
如果后面的数据是另一个 tar 存档,而下一个工具也是另一个,tar
那么该工具将起作用。要提取 N 个串联存档,您需要调用tar
N 次。除非……
GNUtar
支持--ignore-zeros
,因此单个用户tar
可提取部分串联档案。但不是全部。
通常情况下,当 tar 遇到文件条目之间的零块(通常表示档案的结尾)时,它会停止读取。
--ignore-zeros
(-i
)允许 tar 完全读取在结尾之前包含零块的档案(即,损坏的档案或通过将多个档案连接在一起而创建的档案)。
--ignore-zeros
( )选项-i
默认关闭,因为许多版本的 tar 会在存档结束条目后写入垃圾,因为媒体的这一部分永远不应该被读取。[…]
(来源)
首先要尝试的是tar
GNU ( --ignore-zeros
) :-i
./displayFiles | tar -xivf -
如果您不能使用 GNUtar
或任何支持类似 的实现--ignore-zeros
,则需要调用tar
N 次。如果事先不知道 N,则tar
循环运行直至失败:
./displayFiles | while tar -xvf -; do :; done
在最好的情况下,期望This does not look like a tar archive
在关闭其标准输出tar
后尝试读取。displayFiles
请注意,在两个连续的零填充 512 字节记录之后带有额外数据(或垃圾)的 tar 存档仍然有效(即tar
可以正常提取)。如果此类存档进入我们的循环,则下一个tar
将读取额外数据。除了一个或几个极端情况外,额外数据将使工具失败,这将提前结束循环。但即使我们继续循环,除了一个或几个极端情况外,额外数据也会“使流不同步”,并且每个后续文件都将开始tar
读取流,而不是从某个连接的存档开始的地方读取。因此,提前失败并不坏。
希望来自的 tar 档案displayFiles
不包含额外数据。如果包含,则没有简单可靠的方法可以在串联档案流中找到单个档案。无论您使用--ignore-zeros
还是循环,问题都存在。
如果您使用循环,无论如何,其中的一些操作tar
都会失败,而且通常您不知道是否已处理所有数据。因此,请考虑添加一些命令来告诉您流是否已耗尽。示例:
./displayFiles | (while tar -xvf -; do :; done; exit "$(head -c 1 | wc -c)")
(head -c 1
不可移植。可移植替代品dd bs=1 count=1 2>/dev/null
。)
退出状态0
表示所有数据已被tar
进程使用。它仅表示没有其他含义(特别是它不表示没有有意义的错误)。
答案2
tar -f FILE
/tar --file=FILE
仅接受一个文件,因此您要么使用单独的命令将cat
所有文件连接在一起,要么使用循环或tar
对每个文件运行一个命令。while read
xargs