The third form is not at all like the other two, but to understand why we need to go into the order of operations with bash when interpreting the command and see which one is executed when each method is used.
Bash Analysis Steps
- Quotation Processing
- Inclusion of teams
- Analysis of special operators
- Decomposition
- Word separation
- Substitution
- Performance
Using eval "$string"
eval "$string" follows all of the above steps, starting with # 1. Thus:
- Literal quotes inside a string become syntactic quotes
- Special operators processed, such as
>() - Extensions like
$foo run - The results of these decompositions are divided into characters in spaces for individual words
- These words expand like globs if they analyze the same and have available matches, and finally, the command is executed.
Using sh -c "$string"
... does the same as eval , but in a new shell running as a separate process; thus, changes in the state of the variable, the current directory, etc. expire when this new process ends. (Note also that this new shell may be a different interpreter supporting a different language, ie sh -c "foo" will not support the same syntax as bash , ksh , zsh , etc.).
Using $string
... begins with step 5, "Word Separation."
What does it mean?
Quotations are not followed.
Thus,
printf '%s\n' "two words" will be parsed as printf %s\n "two words" , unlike the usual / expected behavior of printf %s\n two words (the quotation marks are consumed by the shell).
The division into several commands (on ; s, & s or similar) does not occur.
Thus:
s='echo foo && echo bar' $s
... will produce the following output:
foo && echo bar
... instead of the following, which would otherwise be expected:
foo bar
Special operations and decompositions are not performed.
No $(foo) , no $foo , no <(foo) , etc.
Redirects fail.
>foo or 2>&1 is just another word created by splitting strings, not a shell directive.
Charles Duffy
source share