Because when you try to execute your command with
$cmd
only one layer of expansion happens. $cmd
contains echo "hello this is a test"
, which is expanded into 6 whitespace-separated tokens:
echo
"hello
this
is
a
test"
and that’s what the set -x
output is showing you: it’s putting single quotes around the tokens that contain double quotes, in order to be clear about what the individual tokens are.
If you want $cmd
to be expanded into a string which then has all the bash quoting rules applied again, try executing your command with:
bash -c "$cmd"
or (as @bitmask points out in the comments, and this is probably more efficient)
eval "$cmd"
instead of just
$cmd