How do I pass on script arguments that contain quotes/spaces?

五迷三道 提交于 2019-11-27 02:06:40

问题


I'm trying to write a script notify-finish that can be prepended to any command. When done, it will run the command given by the arguments following, then email the user when the command is complete. Here's what I have:

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

This works most of the time, but when arguments contain spaces, the quoting is stripped off.

Working example:

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

Failing example:

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

In the second case, $@ is expanded out to rsync -avz -e ssh -c blowfish source user@remote:dest/, missing the single quotes. It does not work with double-quotes either, nor with $*.

After reading other posts I tried putting the command in an array, but I get the exact same issue:

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

How do I make this work for all arguments?


回答1:


Use "$@" with quotes:

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

This will pass each argument exactly as it was received. If you don't include the quotes, each element will be split according to $IFS:

  • "$@" is like "$1" "$2" "$3" ..., passing each element as a separate argument.
  • "$*" is like "$1 $2 $3 ...", passing all elements concatenated as a single argument
  • $* and $@ is like $1 $2 $3 ..., breaking up each element on whitespace, expanding all globs, and passing each resulting word as a separate element ($IFS).

The same is true for arrays, such as "${array[@]}" and "${array[*]}"




回答2:


Put double-quotes around your variable substitutions to keep them from being parsed (note that this applies to all variables: $@, $1, and $PROG). Also: don't put a $ before a variable name when assigning to it; use # for comments; and, on the last line, the single-quotes will prevent variables from being substituted at all.

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"


来源:https://stackoverflow.com/questions/5720194/how-do-i-pass-on-script-arguments-that-contain-quotes-spaces

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!