Variable substitutions should only be used inside double quotes.
calculation='2 * 3'
echo "$calculation" # prints 2 * 3
echo $calculation # prints 2, the list of files in the current directory, and 3
echo "$(($calculation))" # prints 6
Outside of double quotes, $var
takes the value of var
, splits it into whitespace-delimited parts, and interprets each part as a glob (wildcard) pattern. Unless you want this behavior, always put $var
inside double quotes: "$var"
.
The same applies to command substitutions: "$(mycommand)"
is the output of mycommand
, $(mycommand)
is the result of split+glob on the output.
echo "$var" # good
echo "$(mycommand)" # good
another=$var # also works, assignment is implicitly double-quoted
make -D THING=$var # BAD! This is not a bash assignment.
make -D THING="$var" # good
make -D "THING=$var" # also good
Command substitutions get their own quoting contexts. Writing arbitrarily nested substitutions is easy because the parser will keep track of nesting depth instead of greedily searching for the first "
character. The StackOverflow syntax highlighter parses this wrong, however. For example:
echo "formatted text: $(printf "a + b = %04d" "${c}")" # “formatted text: a + b = 0000”
Variable arguments to a command substitution should be double-quoted inside the expansions as well:
echo "$(mycommand "$arg1" "$arg2")"