如何使 xargs 使用 -n 追加尾随参数?

How to make xargs append trailing arguments with -n?

xargs 擅长插入初始参数:

seq 0 10 | xargs -n 3 echo foo

产生这个输出:

foo 0 1 2
foo 3 4 5
foo 6 7 8
foo 9 10

当我还需要尾随参数时怎么办? 即什么命令:

seq 0 10 | xargs -n 3 <WHAT GOES HERE?>

将产生以下所需的输出:

foo 0 1 2 bar
foo 3 4 5 bar
foo 6 7 8 bar
foo 9 10 bar

我尝试了以下方法:

seq 0 10 | xargs -n 3 -I {} echo foo {} bar

这几乎是正确的,除了它显然强制每个命令行 1 项,这不是我想要的:

foo 0 bar
foo 1 bar
foo 2 bar
foo 3 bar
foo 4 bar
foo 5 bar
foo 6 bar
foo 7 bar
foo 8 bar
foo 9 bar
foo 10 bar

使用xargs的-i参数如:

ls -1 | xargs -t -i echo "Found {} file"

请注意,-t 仅用于显示将要发出的命令。当 运行ning 直播时,不要使用 -t 参数。

{} 被实际参数替换。请注意,这确实意味着每个命令每个文件仅 运行 一次。不是一组文件。如果需要使用不同的替换字符串,请在 -i

之后指定
ls -1 | xargs -t -i[] xargs echo "Found []{} file"

将在文件名后保留 {},现在在 []

出现时替换

实现期望的输出

创建名为 runme.sh

的脚本文件
#!/bin/sh
echo "foo $@ bar"

确保 chmod +X 然后使用

seq 0 10 | xargs -n 3 ./runme.sh

这会产生

foo tests tree.php user_admin.php bar
foo user_domains.php user_group_admin.php utilities.php bar
foo vdef.php bar

从@netniV 的回答中抢先一步弄清楚这一点后, 我现在看到 man page 实际上包含一个示例 显示如何操作:

xargs sh -c 'emacs "$@" < /dev/tty' emacs

Launches the minimum number of copies of Emacs needed, one after the other, to edit the files listed on xargs' standard input. This example achieves the same effect as BSD's -o option, but in a more flexible and portable way.

并且 wikipedia page 显示了类似的技术,最后对虚拟 arg 进行了解释:

Another way to achieve a similar effect is to use a shell as the launched command, and deal with the complexity in that shell, for example:

$ mkdir ~/backups
$ find /path -type f -name '*~' -print0 | xargs -0 bash -c 'for filename; do cp -a "$filename" ~/backups; done' bash

The word bash at the end of the line is interpreted by bash -c as special parameter [=16=]. If the word bash weren't present, the name of the first matched file would be assigned to [=16=] and the file wouldn't be copied to ~/backups. Any word can be used instead of bash, but since [=16=] usually expands to the name of the shell or shell script being executed, bash is a good choice.

所以,这是如何做到的:

seq 0 10 | xargs -n 3 sh -c 'echo foo "$@" bar' some_dummy_string

输出如愿:

foo 0 1 2 bar
foo 3 4 5 bar
foo 6 7 8 bar
foo 9 10 bar