In,
cmd="bash -c 'echo hello'"
$cmd
You're not running the bash -c 'echo hello'
command, you're running the $cmd
simple command.
That unquoted $cmd
means invoking the split+glob operator. Here, with the default value of $IFS
, the content of $cmd
is split into bash
, -c
, 'echo
and hello'
. So, you're running bash
with those 4 arguments, it's as if you had typed:
bash -c "'echo" "hello'"
And that 'echo
code has a missing closing quote (the hello'
argument goes into the $0
of that inline script).
If you want to evaluate the content of $cmd
as shell code, it's
eval "$cmd"
So:
cmd="bash -c 'echo hello'"
foo=$(eval "$cmd")
echo "$foo"
Though you could also use your split+glob operator differently:
cmd='bash,-c,echo hello'
IFS=, # split on comma
set -f # disable glob
foo=$($cmd)
echo "$foo"