了解UNIX命令xargs

了解UNIX命令xargs,unix,xargs,Unix,Xargs,我对此很困惑。需要一些澄清 示例1: pgrep string | xargs ps find . | xargs grep whatever 示例2: pgrep string | xargs ps find . | xargs grep whatever 从示例1中,我得出如下结论: 搜索作为正在运行的进程名称的一部分的“字符串”,并将所有匹配项的进程ID返回到“xargs ps”->,它只是将ps附加到匹配项(即进程ID本身)以获得与以下相同的输出: ps <processi

我对此很困惑。需要一些澄清

示例1:

pgrep string | xargs ps
find . | xargs grep whatever
示例2:

pgrep string | xargs ps
find . | xargs grep whatever
从示例1中,我得出如下结论:

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

ps <processid>
ps
有人能解释一下xargs在这种情况下到底做了什么吗

从示例2中,我得出如下结论:

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

我认为“xargs”会反复将标准输入中的数据附加到给定给xargs的“参数”中(该参数本身通常是UNIX命令)

从xargs()手册页:

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


xargs通常用于将参数分组在一起,以便在向命令传递大量参数时不会出现“参数过多”错误

$ echo 'line1
> line2
> line3
> ...
> lineN ' | xargs cmd1 -a -b
将导致:

$ cmd1 -a -b line1 line2 line3 ... lineN
如果行计数过大,
xargs
cmd1…
分为几次执行
cmd1

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

#!/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
但是

由于超出了最大参数数,因此无法工作(我不确定最大值是多少,但在本例中为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"

由于只有两个参数,因此可以得到正确的结果。xargs的一个很好的例子是使用find为目录中的每个文件获取排序校验和

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

cksum file001.blah file002.blah  file003.blah
将报告三行,每个文件一行,带有所需的校验和。Xargs做了一个魔术——将上一个程序的stdout转换成一个临时的隐藏命令行,以提供给下一个程序。有效的命令行是:

find . | xargs cksum | sort

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

一般情况下xargs是这样使用的

 $sh myscript "1 2 3 4 5" "6 7 8 9 10 11"
prog|xargs实用程序

其中,
prog
应输出一个或多个换行符/空格分隔的结果。诀窍在于,
xargs
不一定为每个结果调用一次
实用程序
,而是将结果拆分为子列表,并为每个子列表调用
实用程序
。如果要强制xargs为每个结果调用
实用程序
,则需要使用
xargs-L1
调用它


请注意,
xargs
向您保证发送到
实用程序的子列表比
ARG_MAX
短(如果您好奇,可以使用
getconf ARG_MAX
获得
ARG_MAX
的当前值),这就是它避免那些可怕的“参数列表变长”错误的方法。

btw,这是我在两个或多个目录中查找重复文件的诀窍中的主要成分,即使它们的名称不同。感谢您的深入了解并将详细信息添加到xargs中,使命令生效。找到xargs——冗长的cksum | sort
find.|grep/| xargs cksum | sort
可用于避免不必要的输出
cksum::是一个目录
@Jarvis,最好将find改为:
find.\-键入d
。我不知道最大值是多少,但绝对不是10。您可以使用$@而不是$*。这不是一个关于如何使用的很好的例子xargs@ghostdog74至于那个尝试:
getconf ARG\u MAX
。这是C程序员当然知道的,但无论如何:“#字节的args+environforexec()”。在Linux上,它在
/usr/include/Linux/limits.h
中定义。至于回答者,保罗:我觉得你的答案可以稍加改进,在“$”和“sh”之间加一个空格。甚至删除“$”,因为它不是命令的一部分。乍一看(在我的例子中,视力差+精疲力竭)它看起来像是一个shell变量。您还应该在脚本中引用bash变量。正如@ghostdog74所指出的,您应该将其更改为“$@”。干杯。好吧,这是我能理解的,但现在它变得更加混乱了。我知道XARG在那里的基本原因,但是当我看到它被用于一个以上的用途(不同的方式)时,它会变得复杂。考虑这个命令“find /ETC -类型D -深度1×xARGS ECHO”,它打印了/ETC文件夹中的所有目录(但不是它们的子目录)。由于echo接受多个参数,结果是一条长线“/etc/dir1/etc/dir2…”。如果您改为调用“find/etc-type d-depth 1 | xargs-L1 echo”,则每个结果都会调用一次echo,从而导致/etc中的每个目录都会自动打印在一行上。如何将命令或选项传递给实用程序?比如说,我想运行uglifyjs并为进入xargs的输入指定和输出文件夹?xargs的行为类似于“命令子替换”(至少在Bash中是这样)。它将多行结果(垂直)转换为一行标记参数列表(水平)。(请注意,在将结果传递给xargs之前,您可能会对结果进行一些过滤(使用sed for ex)。加上xargs处理«过多argu