如何从标准输入构建tar文件?

80

我该如何将信息通过管道输入到 tar 中,并指定文件的名称?


我认为@geekosaur应该感到满意,因为他的回答最符合问题。 - Manolo Carrasco Moñino
我已经更改了选定的答案,你是正确的。 - Kristopher Ives
7个回答

117

类似这样:

tar cfz foo.tgz --files-from=-

但请记住,这种方法并不能适用于所有可能的文件名;你应该考虑使用--null选项,并从find -print0中提供tar。(xargs示例在大量文件列表上无法完全工作,因为它会生成多个tar命令。)


“-T”选项在HP-UX上不可用。 - Peter Mortensen
@PeterMortensen 安装 GNU tar 还是 BSD tar?你需要检查它在 HP-UX 应用商店中可能使用的名称... - dakini
请注意,如果您想在使用find-print0选项和tar--null选项时通过管道传递给sort命令,您还需要为sort命令提供-z选项。 - Steve Jorgensen

23

正如geekosaur所指出的那样,不需要将find的输出导入到xargs中,因为可以直接使用find ... -print0 | tar --null ...find的输出直接导入到tar中。

请注意,在排除归档文件方面,gnutarbsdtar之间存在轻微差异。

# exclude file.tar.gz anywhere in the directory tree to be tar'ed and compressed
find . -print0 | gnutar --null --exclude="file.tar.gz" --no-recursion -czf file.tar.gz --files-from -
find . -print0 | bsdtar --null --exclude="file.tar.gz" -n -czf file.tar.gz -T -

# bsdtar excludes ./file.tar.gz in current directory by default
# further file.tar.gz files in subdirectories will get included though
# bsdtar: ./file.tar.gz: Can't add archive to itself
find . -print0 | bsdtar --null -n -czf file.tar.gz -T -

# gnutar does not exclude ./file.tar.gz in current directory by default
find . -print0 | gnutar --null --no-recursion -czf file.tar.gz --files-from -

如果在当前目录中查找,则只需将../file.tar.gz用作目标即可。 - Johan Boulé
“gnutar”和“bsdtar”是字面意思吗? - Peter Mortensen
@PeterMortensen ... 可以的话,它们是可以的。例如,在Linux中可以使用bsdtar,如果你想使用BSD的tar(1)。 - undefined

19

扩展geekosaur的答案:

find /directory | tar -cf archive.tar -T -

你可以使用-T选项来使用标准输入。

请注意,如果您使用某些条件(例如-name选项)过滤文件,则通常需要在管道中排除目录,否则tar将处理它们的所有内容,这不是您想要的。因此,请使用:

find /directory ! -type d -name "mypattern" | tar -cf archive.tar -T -

如果您不使用-type,则将添加与"mypattern"匹配的所有目录内容!

我认为这种方法比其他方法更好,因为你可以将任何输出到标准输出的内容接到它后面。 - daks
1
你可能想考虑使用 find 命令来指定文件类型。具体来说,我会使用 find -type f 来排除符号链接、字符设备等。 如果你对空目录感兴趣,可以使用 find -type f -o -type d - JamesThomasMoon
@JamesThomasMoon1979,使用find -path dir/to/exclude -prune来排除目录是否比通过type f避免目录更好?另外,您说的是mypattern,但它不是模式而是globbin,因此最好使用find -regex "patter"来匹配模式。 - Herdsman
不建议使用-type f来避免目录,而是推荐使用! -type d。这样做的好处是不会排除其他项目,如符号链接、FIFO等。 - CODE-REaD

4
find /directory > filename
tar -T filename -cf archive.tar

1
这个方法对所有可能的文件名都适用吗(请参见geekosaur的答案)? - Peter Mortensen

3

不必使用管道符,你可以使用反引号,例如:

tar cvzf archive.tgz `ls -1 *`

您可以使用任何生成所需归档文件列表的其他命令,而不是ls -1 *


16
唯一的问题是,如果“ls”命令的输出超出了Shell允许的最大命令行大小,则此方法将无法正常工作。在这种情况下,您必须按照其他答案中提到的方式执行操作,以允许列表任意长。此外,“find[...] -print0”可让您创建具有特殊字符成员的tar文件,而“ls”方法则不行。该方法不如安全且普适。 - Michael Trausch

2

tar程序已经有多种实现方式。例如,在IBM的Unix版本AIX上,tar使用-L选项而不是-T,需要一个文件而不允许使用-表示stdin:

Usage: tar -{c|r|t|u|x} [ -BdDEFhilmopRUsvwZ ] [ -Number ] [ -f TarFil e ]
       [ -b Blocks ] [ -S [ Feet ] | [ Feet@Density ] | [ Blocksb ] ]
       [ -L InputList ] [-X ExcludeFile] [ -N Blocks ] [ -C Directory ] File ...
Usage: tar {c|r|t|u|x} [ bBdDEfFhilLXmNopRsSUvwZ[0-9] ] ]
       [ Blocks ] [ TarFile ] [ InputList ] [ ExcludeFile ]
       [ [ Feet ] | [ Feet@Density ] | [ Blocksb ] ] [-C Directory ] File ...

1

在Windows上使用它时,必须有所不同。不要使用z参数,因为它会导致"无法将归档添加到自身"错误。此外,如果您在Zip文件名中不使用".tar"(当使用z参数时),tar.exe将在zip文件中创建一个没有扩展名的文件,这对大多数人来说是相当无用的。

而且,我认为大多数人希望一个包含文件的单个zip文件,而不是一个包含tar文件的zip文件。这也是不使用z参数的原因。然而,我谈论的是在Windows中使用tar,我不熟悉Linux,可能在那里有所不同。所以在Windows中:

要在目录中创建一个ZIP文件,并将特定文件放入该目录中,请使用:

tar.exe -cf MyZipFilename.zip file1.txt file2.jpg file3.xyz

要在目录中创建一个带有通配符的ZIP文件,请使用以下命令:

tar.exe -cf MyZipFilename.zip *.txt *.jpg *.xyzff

为了让您查看压缩文件,请在中间添加v参数。例如:

tar.exe -cvf MyZipFilename.zip file1.txt file2.jpg file3.xyz

或者

tar.exe -cvf MyZipFilename.zip *.txt *.jpg *.xyzff

在一个目录中创建一个包含该目录中所有文件的ZIP文件,使用以下命令: (诀窍是将--exclude放在开头)
tar.exe --exclude MyZipFilename.zip -cf MyZipFilename.zip *

最后,我不知道你为什么想要使用它,但如果你想使用z命令,那么命令将是:

tar.exe --exclude MyZipFilename.tar.zip -cvzf MyZipFilename.tar.zip *

试一下


不回答原帖的问题:如何使用stdin。 - Tom Warfield
tar-in-zip和tar-in-gzip、tar-in-bzip2以及tar-in-xz在Linux上的原理是相同的。它也通过单一数据流(类似rar/7z中的"solidity")提供了比普通zip更好的压缩效果。但是,是的,我没有在你的回答中看到如何从stdin创建tar文件。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接