xargs不一致行为和-n1参数

时间:2013-01-18 18:13:34

标签: linux shell xargs

我有一个shell脚本

find . -name "*.java" -print0 | xargs -0 grep -Lz 'regular_expression'

以这种方式输出与正则表达式不匹配的文件名:

file1.java
file2.java
...

我理解的方式如下:find查找所需文件并将其名称与\0连接起来。然后xargsfind的输出与\0分开并逐一将其提供给grep

然后我想再添加一个阶段并获得basename个文件。我修改了脚本:

find . -name "*.java" -print0 | xargs -0 grep -LzZ 'regular_expression' | xargs -0 basename

但收到了错误。我开始调查并做了一个临时输出:

find . -name "*.java" -print0 | xargs -0 grep -LzZ 'regular_expression' | xargs -0  echo basename

得到了这个:

basename ./file1.java ./file2.java ./subdir/file1.java ./subdir/file2.java

因此,文件名未被\0拆分。如果xargsgrep一起使用且未xargsbasename分开,我无法理解为什么会将其拆分。

我在后者-n1中使用xargs获得了解决方法。但我仍然不明白为什么我需要它(因为我没有在xargs中使用grep)以及此参数的用途。

希望你能向我解释一下-n1做了什么以及为什么我在后一种用法中需要它,并且在grep中不需要它。

2 个答案:

答案 0 :(得分:3)

-n1告诉xargs 每个参数运行给定的命令

所以,如果你有像

这样的东西
echo file1 file2 file2 | xargs basename

这相当于

basename file1 file2 file2

但如果你这样做

echo file1 file2 file2 | xargs -n1 basename

这会导致xargs运行:

basename file1 
basename file2 
basename file2

至于xargs的{​​{1}}标志,这是-0选项的别名,它告诉--nullxargs上拆分而不是默认的空格。您需要在\0之后使用它,因为find的{​​{1}}带有\0,但-print0的结果是纯空格分隔的标记。

答案 1 :(得分:2)

文件名 \0分割。不同之处在于您使用的命令。 xargs通常采用其标准输入,将其分解为列表(此处,通过拆分NUL),然后将该列表作为额外参数传递给您的命令。所以当你这样做时:

find . -name "*.java" -print0 | xargs -0 grep -Lz 'regular_expression'

实际运行的是:

grep -Lz 'regular_expression' file1.java file2.java file3.java...

在这里,-z并不重要,因为它只影响grep读取标准输入的方式,并且您不会向其标准输入发送任何内容。

因此,当您添加另一个运行xargs的{​​{1}}时,您会得到:

basename

但是basename file1.java file2.java file3.java... 虽然会占用任意数量的文件名参数,但 grep只需要一个而忽略其他参数。

basename所在的位置:它告诉-n 1将其参数列表分成块(1),并多次运行该命令。所以现在运行的是:

xargs

并且所有输出都连接在一起到stdout。