tar可以将b.tar附加到从stdin提取a.tar的a.tar上吗?

gav*_*tty 5 stdin pipe tar archive

这是git-archive-all样式脚本的一部分,该脚本将从git项目及其所有子模块生成单个tarball。

子模块档案必须单独生成并附加到超级项目的档案中。但我想将它们动态添加到超级项目档案中,如下所示:

git archive --format=tar ... > super.tar
# pseudo git foreach submodule ; do
  (cd $submodule && git archive --format=tar ...) | tar -Af super.tar
# done
Run Code Online (Sandbox Code Playgroud)

但是super.tar未被修改。并且tar -Af super.tar -无效。

可以分两个阶段来做,但是我希望自己愚蠢到不知道如何工作。

下面分两步完成:

git archive --format=tar ... > super.tar
# pseudo git foreach submodule ; do
  (cd $submodule && git archive --format=tar ...) > $submodule.tar
  tar -Af super.tar $submodule.tar && rm -f $submodule.tar
# done
Run Code Online (Sandbox Code Playgroud)

mxm*_*nkn 1

tar由于某种原因,对管道的要求出奇地挑剔!我尝试了各种替代方案(见下文)并检查了手册中的所有选项,得出的结论是 GNU tar 1.34 根本不可能做到这一点。

确定后,还有其他选择,例如,bsdtar它与管道和标准输入/标准输出配合得很好。但语法有点不同。您可以使用--append,默认情况下会将整个存档添加到现有存档中。要仅将给定存档内的文件添加到结果存档中,需要@使用特殊前缀,请参阅手册。这个例子对我有用:

sudo apt install libarchive-tools  # package was named bsdtar previously
bsdtar --version
# bsdtar 3.4.3 - libarchive 3.4.3 zlib/1.2.11 liblzma/5.2.5
# bz2lib/1.0.8 liblz4/1.9.3 libzstd/1.4.8
echo foo > bar
# --no-fflags is to avoid the harmless "unknown extended header
# keyword 'SCHILY.fflags'" warning when extracting with GNU tar.
# I also force it to produce ustar because that is what GNU tar
# creates by default afaik.
bsdtar --format=ustar --no-fflags --create --file result.tar bar
tar tvlf result.tar
# -rwx------ user/group   4 2022-04-04 23:29 bar
echo bar > foo
echo argh > oof
Run Code Online (Sandbox Code Playgroud)

通过上面的所有设置来获得一个工作示例,这是您想要的主命令行:

tar -cf /dev/stdout foo oof |
    bsdtar --format=ustar --no-fflags --append --file result.tar @-
tar tvlf result.tar
# -rwx------ user/group   4 2022-04-04 23:29 bar
# -rwx------ user/group   4 2022-04-04 23:40 foo
# -rwx------ user/group   5 2022-04-04 23:40 oof
Run Code Online (Sandbox Code Playgroud)

以下是我尝试过的死路径,如果直接管道不起作用且不-被接受,它们可能会显示一些替代方案。

您可以尝试使用 .-进行进程替换,而不是用作输入<( ... )。因为我不想使用git archive,所以我不得不强制tar压缩到标准输出以创建一些要动态附加的替代输入。但是,使用--file -仅给出:

tar: Refusing to write archive contents to terminal
Run Code Online (Sandbox Code Playgroud)

所以,我不得不欺骗tar使用--file /dev/stdout. 不幸的是,即使这样:

tar: Refusing to write archive contents to terminal
Run Code Online (Sandbox Code Playgroud)

不打印任何警告并且简单地保持super.tar不变。从 stdin 读取而不是使用 FIFO 文件具有相同的结果:

tar -Af super.tar <( tar -cf /dev/stdout foo )
Run Code Online (Sandbox Code Playgroud)