Quoting

Quoting controls how the shell interprets special characters.

Source: src/scripting/expansion.f90 (quote removal at lines 2788-2818)

Overview

Quote TypeSpecial CharactersExpansion
No quotesAll interpretedFull
Double quotes "..."Most preserved$, `, , ! interpreted
Single quotes '...'All preservedNone
Dollar-single $'...'Escape sequencesC-style escapes

Single Quotes

Single quotes preserve everything literally. No expansion occurs.

echo 'Hello $USER'       # Hello $USER (literal)
echo 'Line 1\nLine 2'    # Line 1\nLine 2 (literal)
echo 'It'\''s working'   # It's working (escaped single quote)

Escaping Single Quotes

You cannot include a literal single quote inside single quotes. Use one of these methods:

# End quote, add escaped quote, resume
echo 'It'\''s a test'

# Use double quotes for that part
echo "It's a test"

# Use $'...' syntax
echo $'It\'s a test'

Double Quotes

Double quotes allow:

  • Variable expansion: $var, ${var}
  • Command substitution: $(cmd), `cmd`
  • Arithmetic expansion: $((expr))
  • Escape sequences with backslash

They prevent:

  • Word splitting
  • Glob expansion
name="World"
echo "Hello, $name!"           # Hello, World!
echo "Files: $(ls | wc -l)"    # Files: 42
echo "Path: $HOME/*.txt"       # Path: /home/user/*.txt (no glob)
echo "Tab:\tNewline:\n"        # Literal \t and \n (no interpretation)

Backslash in Double Quotes

Inside double quotes, backslash only escapes these characters:

  • $ - Dollar sign
  • ` - Backtick
  • " - Double quote
  • \ - Backslash itself
  • Newline (line continuation)
echo "Price: \$5"        # Price: $5
echo "Quote: \""         # Quote: "
echo "Backslash: \\"     # Backslash: \
echo "Other: \n"         # Other: \n (backslash preserved)

Dollar-Single Quotes

$'...' interprets C-style escape sequences:

EscapeCharacter
\'Single quote
\"Double quote
\\Backslash
\aAlert (bell)
\bBackspace
\e, \EEscape character
\fForm feed
\nNewline
\rCarriage return
\tHorizontal tab
\vVertical tab
\nnnOctal value (1-3 digits)
\xHHHexadecimal value (1-2 digits)
\uHHHHUnicode point (4 hex digits)
\UHHHHHHHHUnicode point (8 hex digits)
echo $'Line 1\nLine 2'      # Two lines
echo $'Tab\there'           # Tab character
echo $'\x41\x42\x43'        # ABC (hex)
echo $'It\'s working'       # It's working

Backslash Escaping

Outside quotes, backslash escapes the next character:

echo Hello\ World          # Hello World (space preserved)
echo Price\: \$5           # Price: $5
echo \*\?\[                # *?[ (literal glob chars)

Line Continuation

Backslash at end of line continues to next line:

echo "This is a very \
long command that \
spans multiple lines"

Quoting Variables

Always quote variable expansions to prevent word splitting and glob expansion:

file="my file.txt"
cat "$file"              # Correct: passes one argument
cat $file                # Wrong: passes two arguments "my" and "file.txt"

pattern="*.txt"
echo "$pattern"          # *.txt (literal)
echo $pattern            # file1.txt file2.txt (expanded)

Special Cases

Empty Strings

var=""
[ -z "$var" ]            # True (empty string)
[ -z $var ]              # Syntax error! (no argument)

echo ""                  # Empty line
echo                     # Empty line (same effect)

Preserving Whitespace

text="  spaces  "
echo $text               # "spaces" (trimmed)
echo "$text"             # "  spaces  " (preserved)

Arrays and $@

args=("one" "two three" "four")
for arg in "${args[@]}"; do
    echo "Arg: $arg"
done
# Arg: one
# Arg: two three
# Arg: four

for arg in ${args[@]}; do   # Wrong! Word splitting
    echo "Arg: $arg"
done
# Arg: one
# Arg: two
# Arg: three
# Arg: four

Nesting Quotes

Different quote types can be nested:

echo "He said 'hello'"              # He said 'hello'
echo 'She said "goodbye"'           # She said "goodbye"
alias greeting="echo 'Hello!'"      # Works

Same quote types cannot be nested:

echo "She said "hello""             # Wrong
echo "She said \"hello\""           # Correct
echo 'It'\''s fine'                 # Correct (end, escape, resume)

Quote Removal

After all expansions, quotes are removed:

echo "hello"                        # hello (no quotes in output)
cat 'file.txt'                      # Reads file.txt

This is the final step in expansion processing.

Best Practices

  1. Always quote variables: "$var" not $var
  2. Use single quotes for literal strings: 'no $expansion'
  3. Use double quotes when expansion needed: "Hello, $name"
  4. Use $'...' for escape sequences: $'line1\nline2'
  5. Quote command substitutions: "$(cmd)" not $(cmd)