【问题标题】:Understanding the UNIX command xargs了解 UNIX 命令 xargs
【发布时间】:2010-12-26 06:20:32
【问题描述】:

我对此感到非常困惑。需要澄清一下。

示例 1:

pgrep string | xargs ps

示例 2:

find . | xargs grep whatever

从示例 1 中,我收集它是这样的:

搜索一个“字符串”,它是正在运行的进程名称的一部分,并将所有匹配项的进程 ID 返回到 'xargs ps' -> 它只是将 ps 附加到匹配项(它们本身就是进程 ID)到得到相同的输出:

ps <processid>

有人能解释一下 xargs 在这种情况下的真正作用吗?

从示例 2 中,我是这样收集的:

就是从当前工作目录中递归搜索一些“字符串”。 在这里,“xargs”究竟是如何工作的?

我认为'xargs' 反复将来自标准输入的数据附加到给 xargs 的'argument'(这通常是一个 UNIX 命令本身)。

来自 xargs() 手册页:

xargs 从标准输入读取项目,由空格分隔(可以是 用双引号或单引号或反斜杠保护)或换行符,以及 执行命令(默认为 /bin/echo)一次或多次 初始参数后跟从标准输入读取的项目。空行 在标准输入上被忽略。

【问题讨论】:

  • xargs 的作用类似于“命令替代”(至少对于 Bash)。它将多行结果(垂直)转换为单行标记参数列表(水平)。 (请注意,在将结果传递给 xargs 之前,您可能会稍微过滤一下结果(使用 sed for ex)。加上 xargs 处理可能在 linux 内核 2.6.23 之前出现的 « too much arguments » 错误(参见 wikipedia )。这里是another helpful thread

标签: unix xargs


【解决方案1】:

一般xargs是这样使用的

prog | xargs utility

prog 预计会输出一个或多个换行符/空格分隔的结果。诀窍是xargs 不一定为每个结果调用一次utility,而是将结果拆分为子列表并为每个子列表调用utility。如果您想强制 xargs 为每个结果调用 utility,则需要使用 xargs -L1 调用它。

注意xargs 向您保证发送到utility 的子列表比ARG_MAX 短(如果您好奇,可以使用getconf ARG_MAX 获取ARG_MAX 的当前值。)这是如何它避免了那些可怕的 "Argument list to long" 错误。

【讨论】:

  • 嗯,这是我可以理解的,但现在它变得更加混乱了。我知道 xargs 存在的基本原因,但是当我看到它被用于多个目的(以不同的方式)时,它变得令人费解..
  • 考虑这个命令“find /etc -type d -depth 1 | xargs echo”,它会打印 /etc 文件夹中的所有目录(但不是它们的子目录)。由于 echo 需要多个参数,结果是一长行“/etc/dir1 /etc/dir2…”。如果您改为调用“find /etc -type d -depth 1 | xargs -L1 echo”,则每个结果都会调用一次 echo,从而导致 /etc 中的每个目录都单独打印在一行上。
  • 如何将命令或选项传递给实用程序?说,我想运行 uglifyjs 并为进入 xargs 的输入指定和输出文件夹? stackoverflow.com/questions/43149786/…
【解决方案2】:

xargs 所做的一个很好的例子是尝试使用 find 为目录中的每个文件获取排序校验和。

find . | cksum  | sort

只返回一个校验和,不清楚它的校验和是什么。不是我们想要的。管道将标准输出从 find 发送到标准输入以获取 cksum。 cksum 真正想要的是一个命令行参数列表,例如

cksum file001.blah file002.blah  file003.blah

将报告三行,每个文件一行,并带有所需的校验和。 Xargs 做了魔术 - 将前一个程序的标准输出转换为临时和隐藏的命令行以提供给下一个程序。有效的命令行是:

find . | xargs cksum | sort

注意 xargs 和 cksum 之间没有管道。

【讨论】:

  • 顺便说一句,这是我在两个或多个目录中查找重复文件的方法中的主要成分,即使它们的名称不同。
  • 感谢您的洞察力,并在 xargs 中添加详细信息可以使命令生效。找 。 | xargs --verbose cksum |排序
  • find . | grep / | xargs cksum | sort 可用于避免不需要的输出 cksum: .: Is a directory
  • @Jarvis 最好将查找更改为:find . \! -type d
【解决方案3】:
$ echo 'line1
> line2
> line3
> ...
> lineN ' | xargs cmd1 -a -b

将导致:

$ cmd1 -a -b line1 line2 line3 ... lineN

如果行数太大,xargs 会将cmd1 ... 分解为多次执行cmd1

xargs 可用于与传递stdin 行作为位置参数相关的许多其他任务。查看xargs(1) 中大写的-P 选项,用于并行运行多个命令实例。

【讨论】:

    【解决方案4】:
    #!/bin/sh
    #script to echo out the arguments 1 at a time!
    for a in $*
    do
        echo $a
    done
    

    命令

    $sh myscript 1 2 3 4 5
    

    将产生

    1
    2
    3
    4
    5
    

    但是

    $sh myscript 1 2 3 4 5 6 7 8 9 10 11
    

    由于超出了参数的最大数量,因此将无法工作(我实际上不确定最大值是多少,但在本例中假设为 10!)

    为了解决这个问题,我们可以使用

    #!/bin/sh
    #script to echo out the arguments 1 at a time!
    for a in $*
    do
        echo $a | xargs echo
    done
    

    我们可以像这样运行它

     $sh myscript "1 2 3 4 5" "6 7 8 9 10 11"
    

    并得到正确的结果,因为只有 2 个参数

    【讨论】:

    • 我不知道最大值是多少,但绝对不是 10。而且您可以使用 $@ 而不是 $*。这不是如何使用 xargs 的一个很好的例子
    • @ghostdog74 至于那个尝试:getconf ARG_MAX。这是 C 程序员当然知道的,但无论如何:'# bytes of args + environ for exec()'。在 Linux 上,它是在 /usr/include/linux/limits.h 中定义的。是的,你的其他观点。
    • 至于回答者,保罗:我觉得你的答案可以通过在'$'和'sh'之间添加一个空格来稍微改进。甚至删除“$”,因为它不是命令的一部分。乍一看(在我的情况下视力不佳 + 精疲力竭),它看起来像是 shell 变量。您还应该在脚本中引用 bash 变量。同样正如@ghostdog74 指出的那样,您应该将其更改为“$@”。干杯。
    【解决方案5】:

    xargs 通常用于将参数组合在一起,这样您就不会在将大量参数传递给命令时出现“参数过多”错误

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-20
      • 2011-12-11
      • 2011-07-18
      • 2011-07-07
      • 2016-07-13
      • 2016-03-15
      • 1970-01-01
      相关资源
      最近更新 更多