【问题标题】:Add stdin as another file to a tar archive将标准输入作为另一个文件添加到 tar 存档
【发布时间】:2014-11-24 14:39:39
【问题描述】:

我正在尝试将文件从程序输出添加到 tar 存档,而不是先在磁盘上生成它。想想一个文件VERSION,它是在构建脚本运行时自动生成的。我试过了,但取消引用的符号链接只是一个命名管道,而不是一个常规文件:

$ date +%s | \
  tar cf test.tar \
    --dereference \
    --transform="s#/proc/self/fd/0#VERSION#" \
    /proc/self/fd/0 \
    other_files \
    and_folders/

结果应该是一个文件 VERSION,在 tar 存档中带有时间戳,而不会在本地生成文件:

$ tar tf test.tar
VERSION
other_files
and_folders

【问题讨论】:

    标签: bash deployment pipe tar


    【解决方案1】:

    我不知道如何在 JAR 存档中创建“假”文件条目。我会创建一个普通文件,将其添加到存档中,然后将其删除。

    不过,您可能想尝试-A(或--concatenate)选项。这将允许您在 /tmp 中创建文件,将其添加到 TAR 存档中,然后在第二步中附加其余文件。这样,您就可以为 VERSION 文件创建任意路径。

    【讨论】:

    • 谢谢!这基本上就是我现在的做法。执行mktemp,使用--transform=s/tempfile/VERSION/ 将其添加到存档中,然后删除。我只是希望通过某种管道魔术使这一步更简洁。
    • 这是唯一的方法,因为您不能通过管道为 TAR 提供文件名及其内容。 /proc/self/fd/0 不起作用,因为 tar 将链接存档为特殊文件而不是扩展其内容。我也很惊讶--dereference 在这种情况下没有关闭它。
    • 好吧,--dereference 确实有效果:没有,打包的/proc/self/fd/0 仍然是一个符号链接,它是一个命名管道(ls -F 附加一个| 的类型)。但是填充管的用途有限......
    【解决方案2】:

    虽然tar 确实适用于文件,但这并不意味着您必须自己创建临时文件,我建议不要这样做。

    您可以为此使用进程替换(Bash 支持这一点,Fish 在slightly different syntax 中也支持)。

    tar cvaf a.tgz <(echo 1.0.0) file1 file2 -P --transform 's:^/.*:VERSION:'
    

    -P (--absolute-names) 是在这里标识临时文件进行名称转换以重命名它。希望其他文件是本地的。

    如果不是这种情况,并且其他一些文件是通过绝对路径添加的(这可能不是常见的情况),那么您可以澄清转换正则表达式或使用两步解决方案,首先创建存档然后更新它(正如 Aaron 指出的那样)。

    【讨论】:

    • 这与我的/proc 解决方案存在相同的问题:tar 打包管道,而不是常规文件。打开包装时,上面写着:$ cat VERSION\ncat: VERSION: File or folder not found.
    • @Boldewyn 这在不同的 shell 中往往是不同的。 Fish 使用mkfifo(例如/tmp/.psub.O02RnmHZ5g)创建实际的命名管道,并且所提出的方法非常有效。 Bash 使用了一些魔法文件,例如 /dev/fd/63。不幸的是,似乎没有内置方法可以切换到 mkfifo 以在 Bash 中进行进程替换。
    • 有趣!好的,这确实可行,但我一定要在这里 Bash。
    猜你喜欢
    • 2020-04-04
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2014-03-10
    • 2020-04-24
    • 1970-01-01
    相关资源
    最近更新 更多