Reputation: 1074
I am having a hard time understanding this. The following command expand files:
% echo "(echo " * " )"
(echo foo.txt bar.txt )
But this doesnt
% echo "$(echo " * " )"
*
Asterisk * is unquoted. Shouldn't the file globbing happen for both cases? How does command substitution affect this case?
Upvotes: 2
Views: 171
Reputation: 295443
It's helpful to look at the commands individually.
% echo "(echo " * " )"
...has only a single quoting context. Here, ( echo
is quoted, an *
is given unquoted, and then a )
is given quoted.
% echo "$(echo " * " )"
Here, you're performing a command substitution, with the inner command having its own quoting context. Specifically, that inner command is:
# the inner command for the substitution is run first
echo " * "
...which emits *
as its output, as one would expect. Notably, because it has its own quoting context, content starts unquoted, and only becomes quoted when the "
s are seen.
Then, the substitution is performed; because the $()
is inside quotes, that substitution process does not run string-splitting and glob expansion (which, if these steps were followed, would break the output of the inner command into multiple words, and expand each word as a glob).
echo "$(echo "*")"
...thus becomes...
# effectively single-quoted because we already finished running expansions
# so expansions that would be allowed in double-quotes are already finished
echo ' * '
By contrast, if you didn't quote:
echo $(echo "*")
...would become...
echo *
...which would have behavior in line with what you anticipated.
Or, the other way around
echo "$(echo *)"
...would become something akin to
echo 'foo.txt bar.txt'
Upvotes: 3
Reputation: 37288
% echo "$(echo " * " )"
# --------|--------|
#produces | |
# echo " * "
Which is a quoted *
.
Same for the outer echo
you have shown, the output of cmd-substitution is quoted, you only see a *
.
That is to say, what is inside the $( .... )
is processed before the enclosing command is executed.
IHTH
Upvotes: 2