Double quotes are special to the shell. If you enter
exec "/bin/ls"
"quote removal" kicks in, and what the shell really sees is two words, exec
and /bin/ls
.
If you run the same command from a variable, it's different: see "Expansion" in man bash
:
Quote Removal
After the preceding expansions, all unquoted occurrences of the characters \, ', and "
that did not result from one of the above expansions are removed.
As the quotes came from variable expansion, they aren't removed.
Just store the command without quotes:
this_command='exec /bin/ls'
$this_command
For more complex commands involving special characters or filenames containing whitespace, using an array variable might seem better
command=(ls -d 'dir name containing spaces')
"{command[@]}"
Note that wildcards will still be evaluated during the command construction, not when the command runs.
$ touch 'a b'
$ command=(ls *\ *)
$ cd ..
$ "${command[@]}"
ls: cannot access 'a b': No such file or directory