如何使 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
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 bybash -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 ofbash
, 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