28

我正在尝试编写一个notify-finish可以附加到任何命令的脚本。完成后,它将运行以下参数给出的命令,然后在命令完成时向用户发送电子邮件。这是我所拥有的:

PROG=$1
# Run command given by arguments
$@
ECODE=$?
echo -e "Subject: `hostname`: $PROG finished\r\nTo: <$USER>\r\n\r\nExited with $ECODE\r\n" | sendmail $USER

这在大多数情况下都有效,但是当参数包含空格时,引号会被删除。

工作示例:

notify-finished rsync -avz source/ user@remote:dest/

失败的例子:

notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/

在第二种情况下,$@扩展为rsync -avz -e ssh -c blowfish source user@remote:dest/,缺少单引号。它也不适用于双引号,也不适用于$*.

在阅读了其他帖子后,我尝试将命令放入数组中,但我遇到了完全相同的问题:

CMD=(notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/)
${CMD[@]}

我如何使它适用于所有论点?

4

2 回答 2

28

"$@" 引号一起使用:

prog="$1"
"$@"
ecode="$?"
echo "$prog exited with $ecode"

这将完全按照接收到的方式传递每个参数。如果您不包含引号,则每个元素将根据以下内容进行拆分$IFS

  • "$@"就像"$1" "$2" "$3" ...,将每个元素作为单独的参数传递。
  • "$*"就像"$1 $2 $3 ...",将所有连接的元素作为单个参数传递
  • $*$@就像,$1 $2 $3 ...分解空格上的每个元素,扩展所有 glob,并将每个结果单词作为单独的元素 ( $IFS) 传递。

数组也是如此,例如"${array[@]}""${array[*]}"

于 2011-04-19T17:22:59.800 回答
4

在你的变量替换周围加上双引号,以防止它们被解析(请注意,这适用于所有变量:$@$1$PROG)。另外:分配变量名时不要在变量名前加上 $;用于#评论;并且,在最后一行,单引号将完全防止变量被替换。

PROG="$1"
shift
# Run program below
"$PROG" "$@"
ECODE=$? # note: this will always be a number, so it doesn't have to be protected with double-quotes
echo -e "Subject: $(hostname): $PROG finished\r\nTo: <$USER>\r\n\r\nExited with $ECODE\r\n' | sendmail "$USER"
于 2011-04-19T17:42:03.860 回答