xargs sh -c 跳过第一个参数

xargs sh -c skipping the first argument

我正在尝试编写一个使用 find 和 xargs 将旧文件归档到大目录中的脚本。这是行:

find /tmp/messages/ -mtime +9 -print0 | xargs -x -t -0 -n 1000 sh -c 'tar rPf /tmp/backup.tar "$@" && rm -f "$@"; sleep 1 && echo Finished one loop: $(date +"%T")'

该脚本大部分都有效,但每次对 1000 个文件执行 运行 命令时它都会跳过第一个文件,我似乎无法弄清楚原因。

这是另一个示例(我尝试使用更简单的命令来查看会发生什么:

如果我只使用 echo 和 xargs,我可以 运行 一个有效的命令:

$ echo a b c d e f| xargs -n 2 echo "$@"
a b
c d
e f
$ echo a b c d e f| xargs -n 3 echo "$@"
a b c
d e f

另一方面,如果每次打印每组都想休眠,我加sh -c 加一串命令:

$ echo a b c d e f| xargs -n 2 sh -c 'echo "$@"; sleep 1;'
b
d
f
$ echo a b c d e f| xargs -n 3 sh -c 'echo "$@"; sleep 1;'
b c
e f

看到第一项是如何被跳过的了吗?

对这里可能发生的事情有什么想法吗?

提前致谢!如果您需要任何额外信息,请告诉我,我很乐意提供。

sh -cbash -c 的第一个参数是脚本的名称,即 [=15=],当您使用 $@:

时不会打印出来

示例:

echo a b c d e f| xargs -n 3 bash -c 'echo "[=10=] $@"'
a b c
d e f

要解决此问题,您可以将 _ 作为脚本的虚拟名称传递,然后它应该可以工作:

echo a b c d e f| xargs -n 3 bash -c 'echo "$@"' _
a b c
d e f

即使使用您的 sleep 示例也能正常工作:

echo a b c d e f| xargs -n 3 bash -c 'echo "$@"; sleep 1' _
a b c
d e f

在Shell命令语言中@special parameter

Expands to the positional parameters, starting from one.

sh 命令的调用形式如下:

sh -c[OPTIONS] command_string [command_name [argument...]]

来自 -c 选项的文档:

Read commands from the command_string operand. Set the value of special parameter 0 (see Special Parameters) from the value of the command_name operand and the positional parameters (</code>, <code>, and so on) in sequence from the remaining argument operands.

例如,在下面的命令中:

sh -c 'tar czvf arch.tar.gz $@' a b c
  • command_string'tar czvf arch.tar.gz $@',
  • command_namea,
  • 第一个argumentb
  • 第二个argumentc

因此,在命令字符串中 [=27=] 将扩展为 a</code> 将扩展为 <code>b</code> 将扩展为 <code>c,并且$@ 特殊参数将扩展为 b c.

因此,如果要在命令字符串中使用command_name,请参考特殊参数零,即[=27=]