【问题标题】:When to use xargs when piping?管道时何时使用 xargs?
【发布时间】:2016-06-05 23:27:01
【问题描述】:

我是 bash 新手,我正在尝试了解 xargs 的用法,这对我来说仍然不清楚。例如:

history | grep ls

在这里,我正在搜索我的历史记录中的命令ls。在这个命令中,我没有使用xargs,它运行良好。

find /etc - name "*.txt" | xargs ls -l

我这个,我必须使用xargs,但我仍然无法理解其中的区别,我无法正确决定何时使用xargs,何时不使用。

【问题讨论】:

标签: bash xargs


【解决方案1】:

xargs 可以在您需要从一个命令获取输出并将其用作另一个命令的参数时使用。在您的第一个示例中,grep 从标准输入中获取数据,而不是作为参数。所以,xargs 是不需要的。

xargs 从标准输入中获取数据并执行命令。默认情况下,数据作为参数附加到命令的末尾。但是,它可以插入到任何地方,使用占位符作为输入。传统的占位符是{};使用它,您的示例命令可能会写成:

find /etc -name "*.txt" | xargs -I {} ls -l {}

如果您在 /etc 中有 3 个文本文件,您将获得每个文件的完整目录列表。当然,您可以轻松地写ls -l /etc/*.txt 并省去麻烦。

另一个示例允许您重命名这些文件,并要求使用占位符 {} 两次。

find /etc -name "*.txt" | xargs -I {} mv {} {}.bak

这些都是不好的例子,一旦你有一个包含空格的文件名就会中断。您可以通过告诉find 使用空字符分隔文件名来解决此问题。

find /etc -print0 -name "*.txt" | xargs -I {} -0 mv {} {}.bak

我个人的看法是,几乎总是有替代使用 xargs 的方法(例如 -execfind 的参数),学习这些会更好。

【讨论】:

  • 如果你觉得它有用,我用这个:gitlab.com/es20490446e/args
  • 你能解释一下-I {}xargs -I {}中是什么吗?
  • @MohammadFaisal 你读过答案的第二段吗?它指定占位符。
【解决方案2】:

当您使用不带xargs 的管道时,实际数据将输入下一个命令。另一方面,当使用带有xargs 的管道时,实际数据被视为下一个命令的参数。举一个具体的例子,假设您有一个包含a.txtb.txt 的文件夹。 a.txt 只包含一行 'hello world!',而 b.txt 只是空的。

如果你这样做

ls | grep txt

你最终会得到输出:

a.txt
b.txt

如果你这样做了

ls | xargs grep txt

您将一无所获,因为文件 a.txt 和 b.txt 都不包含单词 txt

如果命令是

ls | xargs grep hello

你会得到:

hello world!

这是因为使用xargsls 给出的两个文件名作为参数传递给grep,而不是实际内容。

【讨论】:

    【解决方案3】:

    简短回答:暂时避免使用xargs。当您编写了数十或数百个脚本后,返回xargs

    命令可以从参数(如rm bad_example)获取输入,也可以从stdin 获取输入(不仅仅是rm -i is_this_bad_too 之后问题上的y,还有read answer)。 grepsed 等其他命令将查找参数,当参数未显示输入时,切换到输入。
    您的 grep 示例可以从标准输入正常读取,没有什么特别需要。
    您的 ls 需要 find 的输出作为参数。 xargs 只是扭转局面的一种方式。使用 man xargs 了解有关 xargs 的更多信息。替代品:

    find /etc -name "*.txt" -exec ls -l {} \;
    find /etc -name "*.txt" -ls
    ls -l $(find /etc -name "*.txt" )
    ls /etc/*.txt
    

    当您在 /etc 中有 a nasty filename with spaces.txt 时,首先尝试看看哪个命令最好。

    【讨论】:

      【解决方案4】:

      GNU Parallel 可以做与 xargs 相同的事情,但没有损坏和可利用的“功能”。

      您可以通过查看示例 http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-xargs--n1.-Argument-appending 并浏览教程 http://www.gnu.org/software/parallel/parallel_tutorial.html 来学习 GNU Parallel

      【讨论】:

        【解决方案5】:

        xargs(1) 在读取非 NUL 分隔的输入时很危险(损坏、可利用等)。

        如果您正在使用文件名,请改用 find 的 -exec [command] {} +。 如果可以得到 NUL 分隔的输出,请使用xargs -0

        【讨论】:

        • @SaraHamad :您可以通过将-print0 添加到您的命令行来从您的查找中获取以空字符结尾的字符串。检查你的手册页。 (大多数新版本都有)
        • IFS= read -r -d '' 行以确保读取空分隔输入不是更好吗?
        • @DirkHerrmann 你是对的。虽然我是为一般情况写的。我根据您的评论删除了这部分。
        • “危险(损坏、可利用等)”并不意味着一次性脚本磨碎几十个文件不是超级有用 :)
        • @JakubM。擦去尘土!
        猜你喜欢
        • 2016-04-21
        • 1970-01-01
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        • 2019-01-15
        • 2013-04-24
        • 1970-01-01
        • 2014-07-19
        相关资源
        最近更新 更多