【问题标题】:How to use "xargs" properly when argument list is too long当参数列表太长时如何正确使用“xargs”
【发布时间】:2010-10-15 14:07:45
【问题描述】:

有人可以给我一个在以下操作中使用 xargs 的示例吗?

tar c $dir/temp/*.parse\
    | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma

我从 bash "/bin/tar: Argument list too long" 中得到错误

特别是我正在尝试对大约 4,500 个文件进行 LZMA 压缩;所以这并不奇怪。我只是不知道如何修改上面的内容以使用 xargs 并摆脱错误!谢谢。

【问题讨论】:

    标签: linux bash unix


    【解决方案1】:

    使用 find 将“想要的”文件名通过管道传输到临时文件, 然后使用 tar 和 '--files-from' 命令行选项。

    编辑:

    或将它们直接通过管道相互连接以避免临时文件。

    所以:使用 find 列出想要的文件名 | tar ... --files-from

    【讨论】:

      【解决方案2】:

      扩展 CristopheDs 的答案并假设您使用的是 bash:

      tar c --files-from <(find $dir/temp -maxdepth 1 -name "*.parse") | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma
      

      xargs 在这里对您没有帮助的原因是它会执行多次调用,直到使用完所有参数。这在这里对您没有帮助,因为这会创建您不想要的 几个 tar 存档。

      【讨论】:

      • 我之前在 find 多次调用 tar 时犯了错误,将它们放入 { ... } | lzma...它工作。但随后它每次都会再次打印 tar 标头:p
      • 如果有人发现它并且不清楚它是如何工作的,那么 bash 中的&lt;(command) 会创建一个附加到command 输出的“命名文件描述符”。所以在这种情况下,tar 看到类似--files-from /dev/fd123 的参数,但是从“文件”中读取/dev/fd123 只会给它find 的输出,而不需要实际的临时文件。
      【解决方案3】:

      也许你想要这样的东西?

      find $dir/temp/ -name '*.parse' -print0 | tar --null -T - -c | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma
      

      【讨论】:

        【解决方案4】:

        由于您使用的是 Linux,因此您有 GNU tar,您可以使用“-F -”或“--files-from”选项来读取文件名。

        但是,您也可以使用:

        --use-compress-program="lzma -9"

        指定要使用的压缩程序,只需将压缩文件名作为“tar”命令的目标文件。

        在添加“-j”选项之前,这对于“bzip2”压缩是必要的。

        【讨论】:

          【解决方案5】:

          附注:

          始终,始终避免使用 xargs(1)。这是一个损坏的工具,只有在使用 -0 选项时才有用。即便如此,使用 find(1) 的 -exec 选项或简单的 for 或 while 循环几乎总是更好。

          为什么 xargs 如此糟糕?首先,它将输入拆分为空格,这意味着所有包含空格的文件名都会造成破坏。其次,它尝试成为一个聪明人,并为你解析引号。当您在文件名中使用 包含 引号作为文件名的一部分时,这只会导致更多的头痛,例如歌曲:“我不想错过任何东西.mp3 ”。这只会让 xargs 呕吐并诅咒你,因为你引用了它的输入很糟糕。不,你没有:它应该知道引号不属于输入数据,它们属于 shell 脚本,并且 xargs 没有尝试解析它们的业务。

          请注意,当您将 -0 传递给 xargs(1) 时,它不会进行空格拆分或引号解析。它做了正确的事情,即使用 NULL 字节来分隔文件名。但这意味着您需要为其提供使用 NULL 字节分隔文件名的输入(例如“find -foo -print0”)。这让我们回到:最好只使用 find 的 -exec: "find -foo -exec bar {} +"。

          【讨论】:

          • 很好,很棒的小历史/解释 - 非常感谢!
          • 这就是制作 GNU Parallel 的原因:gnu.org/software/parallel/history.html
          • 您的意思可能是在这种特殊情况下避免使用 xargs ?与 while 循环相反,xargs 提供对并行性的控制。值得一提的是,-d 也禁用引号和反斜杠解释
          • 我认为这些文件名是损坏的,而不是 xargs(1),我觉得这很神奇:-)
          猜你喜欢
          • 1970-01-01
          • 2016-12-13
          • 2019-06-03
          • 2017-11-30
          • 2020-05-09
          • 2014-05-21
          • 2015-04-04
          • 2021-10-26
          • 2014-04-18
          相关资源
          最近更新 更多