77

我在一个目录中有一堆tar文件,我想一次从中提取所有文件。但这似乎没有任何作用:

$ tar xf *.tar

这里发生了什么?如何一次解压一堆文件?

4

3 回答 3

150

这里发生了什么?

最初,该tar命令旨在用于磁带设备。由于一次只tar在一台设备上执行才有意义,因此语法设计为假定只有一台设备。假定传递的第一个文件或目录是保存有问题的存档的设备以及要包含在操作中的存档内容的任何其他文件或目录。因此,对于tar提取(x选项),传递的第一个文件将是存档,所有其他文件将是要提取的文件。因此,如果有两个*.tar文件(例如a.tarb.tar),您的命令将扩展为:

$ tar xf a.tar b.tar

除非a.tar包含一个名为 的文件b.tar,否则该tar命令无关紧要并安静地退出。令人讨厌的是,Solaris 版本tar的返回代码或详细选项 ( ) 都没有报告任何问题v。同时,即使关闭了详细选项,也会GNU tar返回2和垃圾邮件:STDERR

tar: b.tar: Not found in archive
tar: Exiting with failure status due to previous errors

如何一次解压一堆文件?

现在重写接受多个存档文件作为输入为时已晚tar,但解决这个限制并不难。

对于大多数人来说,tar多次运行多个档案是最方便的选择。只传递一个文件tar xf名将按预期提取所有存档文件。一种方法是使用 shellfor循环:

$ for f in *.tar; do tar xf "$f"; done

另一种方法是使用xargs

$ ls *.tar | xargs -i tar xf {}

或者,您可以使用多种替代tar文件阅读器中的一种。最后,真正敬业的程序员可以很容易地编写出tar完全符合要求的替代品。格式很简单,许多编程语言都有可用于读取tar文件的库。例如,如果您是 Perl 程序员,请查看该Archive::Tar模块。

一个警告

盲目地解压一堆文件可能会导致意想不到的问题。最明显的是,一个特定的文件名可能包含在多个tar文件中。由于tar默认情况下会覆盖文件,因此您最终得到的文件的确切版本将取决于档案的处理顺序。更麻烦的是,如果你尝试这个“聪明”的优化,你最终可能会得到一个损坏的文件副本:

for f in *.tar; do
  tar xf "$f" &
done
wait

如果两者都a.tar包含b.tar相同的文件并尝试同时提取它,则结果是不可预测的。

一个相关的问题,尤其是从不受信任的来源获取档案时,是tarbomb的可能性。

一种部分解决方案是自动创建一个新目录以提取到:

for f in *.tar; do 
  d=`basename "$f" .tar`
  mkdir "$d"
  (cd "$d" && tar xf "../$f")
done

如果在存档中使用绝对路径指定文件(这通常是恶意意图的标志),这将无济于事。添加这种检查留给读者作为练习。

于 2009-02-24T22:23:58.483 回答
12

如果所有 tar 文件都在同一个文件夹中,那么我在 tcsh shell 中执行此操作。一直在工作。

find -iname \*.tar -exec tar -xvf {} \;

这与上面的答案相同,我认为更简洁一些。

于 2015-12-31T21:37:09.013 回答
8
find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;
于 2014-06-12T15:08:10.153 回答