Skip to content
AgileLogics
6 min read

Quoting

Prerequisites: Variables

Quoting controls how Bash treats special characters and spaces. Getting it right prevents most shell-script bugs.

Double quotes: variables expand, spaces are kept

name="Ada Lovelace"
echo "Hello, $name"
echo 'Hello, $name'
echo "Cost: \$5"
Hello, Ada Lovelace
Hello, $name
Cost: $5
  • Double quotes ("...") expand variables and command substitutions but keep everything else — including spaces — as one piece of text.
  • Single quotes ('...') keep everything literally: no expansion at all.
  • A backslash escapes a single character: \$ prints a dollar sign.

Why "always quote your variables"

Without quotes, Bash splits a variable's value on spaces (and expands wildcards in it). With file names that contain spaces, that breaks things:

file="my report.txt"
echo "some text" > "$file"

ls $file
echo "---"
ls "$file"
ls: cannot access 'my': No such file or directory
ls: cannot access 'report.txt': No such file or directory
---
my report.txt

Unquoted, $file became two arguments — my and report.txt — neither of which exists. Quoted, it stayed one argument.

Counting arguments shows the splitting directly:

count_args() { echo "$# arguments"; }
words="one two three"
count_args $words
count_args "$words"
3 arguments
1 arguments

(count_args is a small function — functions have their own lesson in Level 2. $# is the number of arguments it received.)

The rule: put double quotes around every variable expansion — "$var" — unless you specifically want splitting.

Special characters

Characters such as *, ?, $, &, |, ;, <, >, (, ), and spaces have special meanings. Quote text that contains them:

echo "Is it ready? Yes & no; maybe."
echo 'Use * to match files'
Is it ready? Yes & no; maybe.
Use * to match files

Common mistakes

  • Unquoted variables — the classic shell bug. ShellCheck (a later lesson) warns about every one.
  • Using single quotes when you wanted a variable to expand.