【问题标题】:xargs sh -c skipping the first argumentxargs sh -c 跳过第一个参数
【发布时间】:2017-04-23 21:55:39
【问题描述】:

我正在尝试编写一个脚本,该脚本使用 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

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

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

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

【问题讨论】:

标签: linux bash shell find xargs


【解决方案1】:

sh -cbash -c 的第一个参数是脚本的名称,即$0,当您使用$@ 时不会打印:

例子:

echo a b c d e f| xargs -n 3 bash -c 'echo "$0 $@"'
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

【讨论】:

  • 在 for 循环的情况下如何做到这一点? echo a b c d e f| xargs sh -c 'for i do echo "$i" ;done'
  • @SenthilAKumar:使用echo a b c d e f| xargs sh -c 'for i; do echo "$i"; done' _
【解决方案2】:

在 Shell 命令语言中,@ special parameter

扩展到位置参数,从一个开始。

sh 命令以下列形式调用:

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

来自-c 选项的文档:

从 command_string 操作数读取命令。从 command_name 操作数的值和位置参数($1$2 等)从其余参数操作数开始依次设置特殊参数 0 的值(请参阅特殊参数)。

例如,在以下命令中:

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

因此,在命令字符串中$0 将扩展为a$1 扩展为b$2 扩展为c,并且$@ 特殊参数将扩展为b c

所以如果你想在命令字符串中使用command_name,请参考特殊参数零,即$0

【讨论】:

    猜你喜欢
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 2013-10-02
    相关资源
    最近更新 更多