Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting
Prev |  | Next

# Chapter 5. Quoting

Quoting means just that, bracketing a string in quotes. This has the effect of protecting special characters in the string from reinterpretation or expansion by the shell or shell script. (A character is "special" if it has an interpretation other than its literal meaning. For example, the asterisk * represents a wild card character in globbing and Regular Expressions).

     bash$ ls -l [Vv]*
     -rw-rw-r--    1 bozo  bozo       324 Apr  2 15:05 VIEWDATA.BAT
     -rw-rw-r--    1 bozo  bozo       507 May  4 14:25 vartrace.sh
     -rw-rw-r--    1 bozo  bozo       539 Apr 14 17:11 viewdata.sh

     bash$ ls -l '[Vv]*'
     ls: [Vv]*: No such file or directory

Certain programs and utilities reinterpret or expand special characters in a quoted string. An important use of quoting is protecting a command-line parameter from the shell, but still letting the calling program expand it.

     bash$ grep '[Ff]irst' *.txt
     file1.txt:This is the first line of file1.txt.
     file2.txt:This is the First line of file2.txt.

Note that the unquoted `grep [Ff]irst *.txt` works under the Bash shell. [1]

Quoting can also suppress echo's "appetite" for newlines.

     bash$ echo $(ls -l)
     total 8 -rw-rw-r-- 1 bo bo 13 Aug 21 12:57 t.sh -rw-rw-r-- 1 bo bo 78 Aug 21 12:57 u.sh

     bash$ echo "$(ls -l)"
     total 8
     -rw-rw-r--  1 bo bo  13 Aug 21 12:57 t.sh
     -rw-rw-r--  1 bo bo  78 Aug 21 12:57 u.sh

# 5.1. Quoting Variables

When referencing a variable, it is generally advisable to enclose its name in double quotes. This prevents reinterpretation of all special characters within the quoted string -- except $, ` (backquote), and \ (escape). [2] Keeping $ as a special character within double quotes permits referencing a quoted variable (`"$variable"`), that is, replacing the variable with its value (see Example 4-1, above).

Use double quotes to prevent word splitting. [3] An argument enclosed in double quotes presents itself as a single word, even if it contains whitespace separators.

       1 List="one two three"
       2
       3 for a in $List     # Splits the variable in parts at whitespace.
       4 do
       5   echo "$a"
       6 done
       7 # one
       8 # two
       9 # three
      10
      11 echo "---"
      12
      13 for a in "$List"   # Preserves whitespace in a single variable.
      14 do #     ^     ^
      15   echo "$a"
      16 done
      17 # one two three

A more elaborate example:

       1 variable1="a variable containing five words"
       2 COMMAND This is $variable1    # Executes COMMAND with 7 arguments:
       3 # "This" "is" "a" "variable" "containing" "five" "words"
       4
       5 COMMAND "This is $variable1"  # Executes COMMAND with 1 argument:
       6 # "This is a variable containing five words"
       7
       8
       9 variable2=""    # Empty.
      10
      11 COMMAND $variable2 $variable2 $variable2
      12                 # Executes COMMAND with no arguments.
      13 COMMAND "$variable2" "$variable2" "$variable2"
      14                 # Executes COMMAND with 3 empty arguments.
      15 COMMAND "$variable2 $variable2 $variable2"
      16                 # Executes COMMAND with 1 argument (2 spaces).
      17
      18 # Thanks, Stéphane Chazelas.

| Enclosing the arguments to an echo statement in double quotes is necessary only when word splitting or preservation of whitespace is an issue.

Example 5-1. Echoing Weird Variables

       1 #!/bin/bash
       2 # weirdvars.sh: Echoing weird variables.
       3
       4 echo
       5
       6 var="'(]\\{}\$\""
       7 echo $var        # '(]\{}$"
       8 echo "$var"      # '(]\{}$"     Doesn't make a difference.
       9
      10 echo
      11
      12 IFS='\'
      13 echo $var        # '(] {}$"     \ converted to space. Why?
      14 echo "$var"      # '(]\{}$"
      15
      16 # Examples above supplied by Stephane Chazelas.
      17
      18 echo
      19
      20 var2="\\\\\""
      21 echo $var2       #   "
      22 echo "$var2"     # \\"
      23 echo
      24 # But ... var2="\\\\"" is illegal. Why?
      25 var3='\\\\'
      26 echo "$var3"     # \\\\
      27 # Strong quoting works, though.
      28
      29
      30 # ************************************************************ #
      31 # As the first example above shows, nesting quotes is permitted.
      32
      33 echo "$(echo '"')"           # "
      34 #    ^           ^
      35
      36
      37 # At times this comes in useful.
      38
      39 var1="Two bits"
      40 echo "\$var1 = "$var1""      # $var1 = Two bits
      41 #    ^                ^
      42
      43 # Or, as Chris Hiestand points out ...
      44
      45 if [[ "$(du "$My_File1")" -gt "$(du "$My_File2")" ]]
      46 #     ^     ^         ^ ^     ^     ^         ^ ^
      47 then
      48   ...
      49 fi
      50 # ************************************************************ #

Single quotes (' ') operate similarly to double quotes, but do not permit referencing variables, since the special meaning of $ is turned off. Within single quotes, every special character except ' gets interpreted literally. Consider single quotes ("full quoting") to be a stricter method of quoting than double quotes ("partial quoting").

Since even the escape character (\) gets a literal interpretation within single quotes, trying to enclose a single quote within single quotes will not yield the expected result.

       1 echo "Why can't I write 's between single quotes"
       2
       3 echo
       4
       5 # The roundabout method.
       6 echo 'Why can'\''t I write '"'"'s between single quotes'
       7 #    |-------|  |----------|   |-----------------------|
       8 # Three single-quoted strings, with escaped and quoted single quotes between.
       9
      10 # This example courtesy of Stéphane Chazelas.

### Notes

[1] | Unless there is a file named `first` in the current working directory. Yet another reason to quote. (Thank you, Harald Koenig, for pointing this out.

[2]

Encapsulating "!" within double quotes gives an error when used from the command line. This is interpreted as a history command. Within a script, though, this problem does not occur, since the Bash history mechanism is disabled then.

Of more concern is the apparently inconsistent behavior of `\` within double quotes, and especially following an echo -e command.

     bash$ echo hello\!
     hello!
     bash$ echo "hello\!"
     hello\!

     bash$ echo \
     >
     bash$ echo "\"
     >
     bash$ echo \a
     a
     bash$ echo "\a"
     \a

     bash$ echo x\ty
     xty
     bash$ echo "x\ty"
     x\ty

     bash$ echo -e x\ty
     xty
     bash$ echo -e "x\ty"
     x       y

Double quotes following an echo sometimes escape `\`. Moreover, the `-e` option to echo causes the "\t" to be interpreted as a tab.

(Thank you, Wayne Pollock, for pointing this out, and Geoff Lee and Daniel Barclay for explaining it.)

[3] | "Word splitting," in this context, means dividing a character string into separate and discrete arguments.

Prev | Home | Next
Special Variable Types | Up | Escaping