当使用正则表达式时,Shell报错'tar: not found in archive'。

51

当我使用tar -xzf *.gz命令提取当前目录下所有 .gz 文件时,会出现Not found in archive错误。但是,如果逐个提取或使用for循环,则可以正常运行。

for file in `ls *.gz`; do tar -xzf $file; done

这个错误的原因是什么?


2
这是由于tar的参数语法只接受命令行中的一个单一tar,其余部分被解释为其他内容。您也可以使用xargs(例如ls *.gz |xargs -n1 tar -xzf或类似命令)。 - ShinTakezou
tar 不接受 glob 模式作为参数(即它不会解释它)据我所知。 - ShinTakezou
@ShinTakezou:但是 shell 会扩展 *.gz 符号;tar 不会(通常)看到 *.gz。有时,您想提取名称中带有 * 的文件。例如:tar -xf abc.tar.gz 'src/prog/*name.*' 将提取诸如 src/prog/bigname.csrc/prog/smallname.h 等文件;单引号防止 shell 扩展 *,而 tar 确实扩展它。 - Jonathan Leffler
@JonathanLeffler 我当然知道。实际上,我写了“tar在命令行中只接受一个单一的tar”,即我想象OP认为tar -xzf *.gz会像其他接受更多文件的命令一样工作,但是tar将“其余部分”解释为其他内容,即tar -xzf 1.gz 2.gz 3.gz只会将1.gz视为“tar”。我忘记指定shell的扩展,但很明显我假设了它。第二条评论回答了现在已删除的评论,该评论建议转义“”(以避免shell扩展)。因此,我指出对于tar来说,“.gz”不是全局模式,除非它解释它,而且据我所知它不会这样做。 - ShinTakezou
我在回应你的第二条评论:就我所知,tar命令不接受glob模式作为参数(也就是说,它不会解释它)。根据我的观察,这意味着你不能像我展示的那样运行;如果需要,tar确实会扩展glob模式。 - Jonathan Leffler
3个回答

70
当你编写代码时。
 tar -xzf *.gz

你的shell会将其扩展为字符串:

 tar -xzf 1.gz 2.gz 3.gz

(假设您当前目录中有1.gz、2.gz和3.gz文件。)

tar认为您想从1.gz中提取2.gz3.gz;由于档案中找不到这些文件,因此会导致错误信息。

您需要使用xargs命令的循环for来提取您的文件。

ls *.gz |xargs -n1 tar -xzf

这意味着:对于当前目录中的每个gz文件,请运行tar -xzf命令。


42

当你写:

tar -xf *.gz

tar命令看到的内容举例:

tar -xf abc.tar.gz def.tar.gz ghi.tar.gz
这被解释为从归档文件abc.tar.gz中提取def.tar.gzghi.tar.gz,但由于文件不在其中,您会收到警告消息。
换句话说,tar一次仅操作单个tar文件(可能已压缩)。它不操作多个tar文件。
请注意,如果abc.tar.gz包含一个文件pqr/xyz/important.c,则可以通过指定以下内容仅提取一个文件:
tar -xf abc.tar.gz pqr/xyz/important.c

你使用的符号只是此符号的变体。

(是的,有时会有压缩文件中包含压缩文件的情况。例如,Gmail不允许您发送包含可执行文件的tar文件或gzipped tar文件。但是,如果将一个gzipped tar文件嵌入到一个未压缩的tar文件中,则不会查找内部文件以查找可执行文件。当我需要发送包含可执行的configure脚本的tar文件时,我会使用这种方法。)


5
主要原因是tar只接受单个文件名参数。当你调用tar *.tgz时,bash会将*扩展到所有带有tgz格式的文件名上,变成tar file1 file2 file3,这被tar所不接受。所以,你可以使用for循环,例如:for i in *.tgz; do tar -zxvf $i ;done,或者使用一些其他命令来间接执行tar,如评论中所示,如lsfind . -maxdepth 1 -name \*tgz -exec tar -zxvf {} \;ls的输出始终存在风险)。

为什么ls命令的输出总是具有风险? - notbad
如果名称包含空格或换行符,则 ls 命令的输出是不明确的。对于没有空格的名称(包括没有换行符的),这没问题,但是现在不能依赖没有空格的名称。 - Jonathan Leffler
1
for i in *.tgz; do tar -zxvf "$i" ;done 更好地工作。 - rjpj1998

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