What are the shell statements where expanding a variable with or without double quotes is 100% equivalent?

Viewed 145

Let's suppose that you have a variable which is subject to word splitting, globing and pattern matching:

var='*
.?'

While I'm pretty sure that everyone agrees that "$var" is the best way to expand the variable as a string literal, I've identified a few cases where you don't need to use the double quotes:

  • Simple assignment: x=$var

  • Case statement: case $var in ...

  • Leftmost part of bash test construct: [[ $var .... ]]

  • UPDATE1: Bash here-string: <<< $var which works starting from bash-4.4 (thank you @GordonDavidson)

  • UPDATE2: Exported assignment (in bash): export x=$var

Is it correct? Is there any other shell/bash statement where the variable isn't subject to glob expansion or word splitting without using double-quotes? where expanding a variable with or without double quotes is 100% equivalent?


The reason why I ask this question is that when reading foreign code, knowing the above mentioned border-cases might help.

For example, one bug that I found in a script that I was debugging is something like:

out_exists="-f a.out"
[[ $out_exists ]] && mv a.out prog.exe
mv: cannot stat ‘a.out’: No such file or directory
2 Answers

This question is a duplicate of What are the contexts where Bash doesn't perform word splitting and globbing?, but that was closed before it was answered.

For a thorough answer to the question see the answer by Stéphane Chazelas to What are the contexts where Bash doesn't perform word splitting and globbing? - Unix & Linux Stack Exchange. Another good answer is in the "Where you can omit the double quotes" section in the answer by Gilles to When is double-quoting necessary? - Unix & Linux Stack Exchange.

There seem to be a small number of cases that aren't covered by the links above:

  • With the for (( expr1 ; expr2 ; expr3 )) ... loop, variable expansions in any of the expressions inside the (( ... )) don't need to be quoted.
  • Several of the expansions described in the Shell Parameter Expansion section of the Bash Reference Manual are described with a word argument that isn't subject to word splitting or pathname expansion (globbing). Examples include ${parameter:-word}, ${parameter#word}, and ${parameter%word}.

Great question! If you need to word split a variable, the quotes should be left off.

If I think of other cases, I'll add to this.

var='abc xyz'

set "$var"
echo $1
abc xyz

set $var
echo $1
abc
Related