我可以运行这个命令并且它有效:
find . -type f -print0 | xargs md5sum
这将打印每个文件的 md5sum。
但对于其他命令,它似乎将所有文件传递给命令的单次调用。例如,printf
和echo
似乎都有这个问题。我printf
收到这个警告:
printf: warning: ignoring excess arguments, starting with ...
当使用 echo 时,它只打印一行,例如,如果我有以下命令:
find . -type f -print0 | xargs -r0 echo GOT
我只看到“GOT”打印一次,与找到的所有文件在同一行。
我想也许是因为 echo 也是内置的,但如果我显式运行 /bin/echo ,我会得到相同的行为。
作为参考,我什至在制造命令中遇到了这个问题:
$ echo "a b c" | xargs echo GOT
GOT a b c
代替:
GOT a
GOT b
GOT c
我究竟做错了什么?首先通过在命令前面加上前缀来调试命令对我很有帮助echo
,但我什至无法做到这一点。
编辑:正如评论中提到的,我实际上无法使用该-exec
选项find
,实际上我的管道有点长,其中包含排序,但这似乎是一个无关的细节,与我无法获得的事实无关甚至更简单的管道工作。
答案1
您可以将其视为xargs command-arg
运行单个实例的命令,该命令command-arg
从标准输入获得的所有内容均附加在其后面,并由某个分隔符(默认为空格或您在示例中使用的 NUL 字节)分隔。例如:
echo 1 2 3 | xargs something
会跑something 1 2 3
。或者使用您在问题中发布的示例:
echo "a b c" | xargs echo GOT
运行echo GOT a b c
。
如果你想使用从标准输入获得的每个参数 xargs 来创建一个新的 command-arg 实例,你可以使用 -n1 选项:
$ echo "a b c" | xargs -n1 echo GOT
GOT a
GOT b
GOT c
当然请注意,某些命令不接受多个参数,因此必须始终使用-n1
.
使用 xargs 的优点是生成新进程是一项昂贵的操作,因此使用多个参数运行单个进程会更快,请检查我在这个答案中所做的一些基准测试 https://unix.stackexchange.com/a/536023/72304
答案2
除了-n1
第一个答案中提到的“use”之外,您的 shell 可能还有某些命令的内置版本。如果从不同的程序(例如,从 )调用命令xargs
,它将调用外部程序而不是 shell 的内置版本。
特别是,printf
它内置于 Bash 和其他几个 shell 中,并且 Bash 的内置版本将根据需要多次重复该格式以用完所有参数。
例如,使用 Bash 的内置版本,
printf '%s and %s\n' How now brown cow
将输出 2 行,而
/usr/bin/printf '%s and %s\n' How now brown cow
可能会抱怨它有太多参数,具体取决于您安装的版本。
答案3
通常我会避免xargs
。
您在网络上找到的大多数示例都很脆弱 - 如果环境与编写代码的人的假设不匹配,它们就会以意想不到的方式崩溃。
即使这个问题中给出的例子也有一个错误:它使用find
...-print0
但是然后使用xargs
没有 -0
。
此外,大多数使用xargs
都是不必要的。特别是,当它与 结合使用时,在 中find
使用表达式既更可靠又不易出错。-exec
find
给出的示例可以替换为:
find . -type f -exec md5sum {} +