Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
475 views
in Technique[技术] by (71.8m points)

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

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
To: <$USER>

Exited with $ECODE
" | 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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[*]}"


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...