【问题标题】:How can you untar more than one file at a time?如何一次解压多个文件?
【发布时间】:2009-02-24 22:23:46
【问题描述】:

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

$ tar xf *.tar

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

【问题讨论】:

    标签: unix shell tar


    【解决方案1】:

    这是怎么回事?

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

    $ tar xf a.tar b.tar
    

    除非a.tar 包含一个名为b.tar 的文件,否则tar 命令没有任何作用并安静地退出。令人讨厌的是,tar 的 Solaris 版本在返回代码或详细选项 (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 将按预期提取所有存档文件。一种方法是使用 shell for 循环:

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

    另一种方法是使用xargs:

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

    或者,您可以使用多个alternative tar file readers 之一。最后,真正敬业的程序员可以轻松地编写一个完全符合要求的tar 替换。 format 很简单,许多编程语言都有可用于读取tar 文件的库。例如,如果您是 Perl 程序员,请查看 Archive::Tar 模块。

    警告

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

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

    如果a.tarb.tar 都包含同一个文件并尝试同时提取它,结果是不可预测的。

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

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

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

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

    【讨论】:

    • 我的 tar 手册页显示“-l 和 -i 选项出现在 1997 版 POSIX 标准中,但未出现在 2004 版标准中。因此您应该使用 -L 和-我分别代替。”对于这个任务,我会小心使用 xargs 并使用“-n1”来避免最初的问题。
    • @slacy:我认为您的意思是 GNU xargs 联机帮助页。我想你是对的,但我真的不喜欢这样的结果:“xargs -I {} tar xf {}”。另一方面,“-n1”在这种情况下可以正常工作:“| xargs -n1 tar tf”。这甚至是一种改进。但这对这只老狗来说是一个新把戏。 ;-)
    • 很好的答案,但我想补充一点,如果其中一个 tar 包含空格,这将失败,除非我们在 tar 参数周围加上引号:for f in *.tar; do tar xf "$f"; done
    • 很好的解释!
    【解决方案2】:

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

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

    这和上面的答案一样,我觉得更简洁一点。

    【讨论】:

      【解决方案3】:
      find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;
      

      【讨论】:

      • 解释一下代码的作用会有用!
      猜你喜欢
      • 2019-01-06
      • 1970-01-01
      • 2013-06-17
      • 2018-09-23
      • 2018-05-10
      • 1970-01-01
      • 2015-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多