Quoting
Quoting controls how the shell interprets special characters.
Source: src/scripting/expansion.f90 (quote removal at lines 2788-2818)
Overview
| Quote Type | Special Characters | Expansion |
|---|---|---|
| No quotes | All interpreted | Full |
Double quotes "..." | Most preserved | $, `, , ! interpreted |
Single quotes '...' | All preserved | None |
Dollar-single $'...' | Escape sequences | C-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:
| Escape | Character |
|---|---|
\' | Single quote |
\" | Double quote |
\\ | Backslash |
\a | Alert (bell) |
\b | Backspace |
\e, \E | Escape character |
\f | Form feed |
\n | Newline |
\r | Carriage return |
\t | Horizontal tab |
\v | Vertical tab |
\nnn | Octal value (1-3 digits) |
\xHH | Hexadecimal value (1-2 digits) |
\uHHHH | Unicode point (4 hex digits) |
\UHHHHHHHH | Unicode 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
- Always quote variables:
"$var"not$var - Use single quotes for literal strings:
'no $expansion' - Use double quotes when expansion needed:
"Hello, $name" - Use
$'...'for escape sequences:$'line1\nline2' - Quote command substitutions:
"$(cmd)"not$(cmd)