Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

bash

quoting

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?

like image 434
axon Avatar asked Apr 19 '11 17:04

axon


People also ask

How do you pass quotes in a bash script?

When you want to pass all the arguments to another script, or function, use "$@" (without escaping your quotes). See this answer: Difference between single and double quotes in Bash.

How do you pass arguments in a script?

Using arguments Inside the script, we can use the $ symbol followed by the integer to access the arguments passed. For example, $1 , $2 , and so on. The $0 will contain the script name.

How do you escape a quote in a shell script?

You can use backslash(\) or double quotes(") to escape single quotes in bash shell script. Backslash escapes the character that immediately follows it. By using single quotes inside double quotes, you can escape it.


1 Answers

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

like image 171
Michał Šrajer Avatar answered Nov 04 '22 07:11

Michał Šrajer