Issue
I need to insert an array of arguments into an eval
string executed via bash -c
.
In this particular case, it's not possible to pass them separately as proper arguments (it's for an flock
invocation which doesn't accept arguments for a -c
script).
Smth like this:
flock f.lock -c 'do_stuff '"${ARGS[@]}"'; do_other_stuff'
How do I quote them properly so that they are correctly parsed into a sequence of arguments, even if they contain spaces or Bash special syntax?
Solution
Use Parameter transformation (new in Bash 4.4) with the Q (quote) operator which is specifically designed for this:
Q The expansion is a string that is the value of parameter quoted in a format that can be reused as input.
$ ARGS=("foo bar" 'baz\n'\' '$xyzzy')
$ echo 'do_stuff '"${ARGS[*]@Q}"'; do_other_stuff'
do_stuff 'foo bar' 'baz\n'\''' '$xyzzy'; do_other_stuff
Note the use of *
instead of the usual @
since the code needs to be a single argument. Using @
leads to erroneous behavior in some cases:
$ bash -xc "echo ${ARGS[@]@Q}; do_other_stuff"
+ echo 'foo bar'
foo bar
$ bash -xc "echo ${ARGS[*]@Q}; do_other_stuff"
+ echo 'foo bar' 'baz\n'\''' '$xyzzy'
foo bar baz\n' $xyzzy
+ do_other_stuff
You can even use this syntax for $*
:
'do_stuff '"${*@Q}"' other args; do other stuff'
Answered By - ivan_pozdeev Answer Checked By - David Marino (WPSolving Volunteer)