Search code examples
shellescapingargumentsquotessh

Pass shell-escaped string of arguments to a subcommand in Bourne shell


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?


Solution

  • One possibility is to use eval:

    #!/bin/sh
    
    args="--foo 'bar baz' qux"
    cmd="python -c 'import sys; print sys.argv'"
    
    eval $cmd $args
    

    That way you cause the command line to be interpreted rather than just split according to IFS. This gives the output:

    $ ./args.sh 
    ['-c', '--foo', 'bar baz', 'qux']
    

    So that you can see the args are passed as you wanted.