从 /dev/stdin 文件生成 tar

从 /dev/stdin 文件生成 tar

我正在寻找一种通过 STDIN 传递任意数据的方法,并将其像普通文件一样进行压缩。

我试过这个

$ echo test | tar -cf test.tar /dev/stdin

这给了我一个test.tar包含内容的文件dev/stdin。该stdin文件是 的链接/proc/self/fd/0

我想要的是dev/stdinTAR 文件内部是一个包含文本的常规文件test。类似的情况也发生在:

$ tar -cf test.tar <(echo test)

但名称不同。

这可行吗?

答案1

我认为你不能在这里做你想做的事。您的方法的问题在于tar处理文件和目录树,而您没有为其提供如下命令:

$ echo test | tar -cf test.tar /dev/sdtin

即使您尝试使用如下子 shell 将字符串“包装”在临时文件中:

$ tar -cf test.tar <(echo test)

您可以看到您的内容仍在使用这些临时文件描述符进行 TAR 压缩:

$ tar tvf test.tar
lr-x------ vagrant/vagrant   0 2018-08-04 23:52 dev/fd/63 -> pipe:[102734]

如果您只想压缩字符串,则需要将它们放入文件上下文中。所以你需要做这样的事情:

$ echo "test" > somefile && tar -cf /tmp/test.tar somefile

您可以看到该文件存在于 TAR 文件中:

$ tar tvf /tmp/test.tar
-rw-rw-r-- vagrant/vagrant   5 2018-08-05 00:00 somefile

使用 tar 复制数据

大多数使用 Unix 多年的人可能都见过这种模式:

$ (cd /; tar cf - .)|(cd /mnt/newroot; tar pxvf -)

我过去一直使用它来将数据从一个位置复制到另一个位置。您也可以通过 SSH 使用它。其他方法在 U&L Q&A 中讨论,标题为:使用 busybox 克隆根目录树

备份 /

如果您打算备份整个硬盘,还可以使用此方法:

$ sudo tar -cvpzf backup.tar.gz --exclude=/backup.tar.gz --one-file-system /

参考

答案2

如果您知道要传输的内容的最终大小(以字节为单位),则可以将 tar 文件创建为流。然后,需要在数据流之前创建初始 512 字节标头,并在其之后创建尾部填充。尽管它确实取决于tar文件的确切变体,因为有几种不同的文件格式。以下步骤可能适合您:

  1. 创建与数据流大小相同的空洞文件

    $ dd if=/dev/zero of=mystream bs=1 count=0 seek=$SIZE

    请注意,mystream现在它是一个“洞”文件,实际上并不占用磁盘空间,即使它看起来与数据流具有相同的大小 $SIZE。

  2. 用于为指定大小的tar文件创建标头mystream

    $ tar cf - mystream | head -c 512 > header

    请注意,tar将希望创建一个没有漏洞的文件,因此丢弃除前 512 字节之外的所有内容非常重要。然后删除洞文件,以免被意外复制。

    $ rm mystream

  3. 创建一个填充尾部以填充 512 个块。

    $ head -c $((echo "scale=0; 512 - $SIZE % 512" | bc )) > trailer

  4. 制作带有标头和标尾的 $STREAM(大小为 $SIZE)的 tar 流

    $ cat header $STREAM trailer

    请注意,您可能希望将其流式传输到标准输出以外的其他地方。

答案3

使用zsh,您可以使用=(...)进程替换的形式,它使用临时文件而不是管道。使用 GNUtar--transform选项,您可以更改存档成员的名称:

tar --transform='s/.*/test-file/' -zcf file.tar.gz =(echo test)

将创建一个 file.tar.gz包含一名test-file具有权限 0600 和 content 的成员的test\n.

使用bash(或zsh),您可以执行以下操作:

tar --transform='s/.*/test-file/' -zchf file.tar.gz /dev/stdin <<< "$(echo test)"

Here-strings 也在这些 shell 中使用临时文件。但请注意,命令替换会删除每一个尾随换行符并添加back 和 inbash会剥离 NUL 字节。

相关内容