Say I have a command I want to run (cmd) and a variable containing the arguments I want to pass to the function (something like --foo 'bar baz' qux). Like so:
#!/bin/sh
command=cmd
args="--foo 'bar baz' qux"
The arguments contain quotes, like the ones shown above, that group together an argument containing a space. I'd then like to run the command:
$command $args
This, of course, results in running the command with four arguments: --foo, 'bar, baz', and qux. The alternative I'm used to (i.e., when using "$@") presents a different problem:
$command "$args"
This executes the command with one argument: --foo 'bar baz' qux.
How can I run the command with three arguments (--foo, bar baz, and qux) as intended?
Use an array to specify your argument list exactly, without string-splitting (which is what's doing the wrong thing here) getting in your way:
args=( --foo "bar baz" qux )
command "${args[@]}"
If you need to build your argument list dynamically, you can append to arrays with +=:
args=( )
while ...; do
args+=( "$another_argument" )
done
call_your_subprocess "${args[@]}"
Note that the use of quotation marks, and [@] instead of [*], is essential.
If you can throw away the current positional variables ($1...) you can use the following:
set -- '--foo' 'bar baz' 'qux'
echo "$#" # Prints "3" (without quotes)
echo "$2" # Prints "bar baz" (without quotes)
command "$@"
Just tested it in a #!/usr/bin/env sh script, so it works at least in Dash, and should work in any Bourne Shell variant. No eval, Python or Bash necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With