Reputation: 105053
I have a bash variable:
A="test; ls"
I want to use it as part of a call:
echo $A
I'm expecting it to be expanded into:
echo test; ls
However, it is expanded:
echo "test;" "ls"
How is it possible to achieve what I want? The only solution I can think of is this:
bash -c "echo $A"
Maybe there is something more elegant?
Upvotes: 0
Views: 84
Reputation: 295298
If you're building compound commands, running redirections, etc., then you need to use eval:
A="test; ls"
eval "$A"
However, it's far better not to do this. A typical use case that follows good practices follows:
my_cmd=( something --some-arg "another argument with spaces" )
if [[ $foo ]]; then
my_cmd+=( --foo="$foo" )
fi
"${my_cmd[@]}"
Unlike the eval
version, this can only run a single command line, and will run it exactly as-given -- meaning that even if foo='$(rm -rf /)'
you won't get your hard drive wiped. :)
If you absolutely must use eval
, or are forming a shell command to be used in a context where it will necessarily be shell-evaluated (for instance, passed on a ssh
command line), you can achieve a hybrid approach using printf %q
to form command lines safe for eval:
printf -v cmd_str 'ls -l %q; exit 1' "some potentially malicious string"
eval "$cmd_str"
See BashFAQ #48 for more details on the eval
command and why it should be used only with great care, or BashFAQ #50 for a general discussion of pitfalls and best practices around programmatically constructing commands. (Note that bash -c "$cmd_str"
is equivalent to eval in terms of security impact, and requires the same precautions to use safely).
Upvotes: 3