20 20. Single Quotes vs. Double Quotes
You have already used both kinds of quotes to keep text together. Now that you know about environment variables, you can understand the important difference between them. Quotes appear in almost every real command, including the commands AI tools write for you, so it pays to read them correctly.
20.1 Recap: both kinds keep text together
Both "double quotes" and 'single quotes' keep spaces and special characters together as one piece of text (see Writing to Files):
echo "Hello World"
echo 'Hello World'Output:
Hello World
Hello World
So far they look identical. The difference shows up as soon as the text contains a $.
20.2 The difference: $ works only inside double quotes
- Inside double quotes, the shell still looks for
$. It replaces$NAME(or${NAME}) with the variable’s value, and$(command)with the output of that command. Everything else is kept as typed. - Inside single quotes, nothing is changed. The text is literal: exactly what you typed, character for character.
Here is Maria on her Mac:
echo "Home: $HOME"
echo 'Home: $HOME'Output:
Home: /Users/maria
Home: $HOME
price=20
echo "Price: $price dollars"
echo 'Price: $price dollars'Output:
Price: 20 dollars
Price: $price dollars
$(command) is called command substitution: the shell runs the command and puts its output into the text. It also works only inside double quotes (or with no quotes at all):
cd ~/Documents/bash-tutorial-files
echo "I am in $(pwd)"
echo 'I am in $(pwd)'Output:
I am in /Users/maria/Documents/bash-tutorial-files
I am in $(pwd)
A simple way to remember: single quotes mean “say exactly this”; double quotes mean “say this, but fill in the variables first.”
"double quotes" |
'single quotes' |
|
|---|---|---|
Keep spaces and >, ;, *, ~ … as plain text |
yes | yes |
$NAME and ${NAME} |
replaced with the variable’s value | kept as typed |
$(command) |
replaced with the command’s output | kept as typed |
A backslash \ before $ or " |
makes it a plain character | kept as typed |
20.3 When a $ should stay a $
Money amounts are a classic surprise:
echo "The total is $5"Output:
The total is
The shell read $5 as a variable (a special one that scripts use, see Bash Scripts). It’s empty here, so it disappeared. Two fixes:
echo 'The total is $5'
echo "The total is \$5"Output:
The total is $5
The total is $5
Inside double quotes, a backslash (\) in front of $ “escapes” it: it tells the shell to treat the next character as an ordinary character. The same rule matters for Git commit messages you will write later: use git commit -m 'Fix $10 discount bug', not double quotes.
20.4 Quotes inside quotes
- To include an apostrophe, use double quotes:
echo "It's Maria's laptop" - To include double quotes, use single quotes:
echo 'He said "hi"' - To include a double quote and a
$inside double quotes, escape them with backslashes:
echo "She said \"wow\" and paid \$20"Output:
She said "wow" and paid $20
A single quote can never appear inside single quotes (not even with a backslash), so switch to double quotes when your text contains an apostrophe.
>, quote>, or dquote> prompt?
If your quotes don’t match, as in echo 'It's raining' (three single quotes), the shell waits for you to close the quote. Git Bash shows a > prompt; zsh on a Mac shows quote> or dquote>. Press Ctrl+C to cancel, then retype the command with matching quotes: echo "It's raining".
20.5 No quotes: spaces, wildcards, and ~
Without quotes, the shell does more work before it runs a command:
- it splits the line into separate words at the spaces,
- it expands wildcards such as
*into matching file names (see Wildcards and Pipes), - it replaces a
~at the start of a word with your home directory.
Quotes (of either kind) turn all of this off. In the notes practice folder:
echo Files: *.txt
echo "Files: *.txt"Output:
Files: ideas.txt meeting-notes.txt
Files: *.txt
20.5.1 Always quote variables that hold file names
In Bash, even the value of an unquoted variable is split at spaces. Suppose a folder contains a file named Q3 report.txt:
file="Q3 report.txt"
cat $filezsh (the Mac’s default shell) does not split variables this way, so this unquoted command happens to work at the Mac prompt. It fails as soon as the same command runs in Bash, for example inside a Bash script, which is why you should quote anyway.
Output:
cat: Q3: No such file or directory
cat: report.txt: No such file or directory
Bash split the value into two words, so cat looked for two files, Q3 and report.txt.
The fix works everywhere: put the variable in double quotes, cat "$file". Double quotes keep the value together while still filling it in.
20.5.2 ~ doesn’t work inside quotes
ls "~/Documents" fails with “No such file or directory”, because inside quotes ~ is just a character (see Files, Folders, and Paths). To combine your home folder with a name that contains spaces, use $HOME inside double quotes, or leave the ~/ outside the quotes:
ls "$HOME/My Projects"
ls ~/"My Projects"20.6 Rules of thumb
- Text that must stay exactly as typed (prices, commit messages, passwords in examples, search patterns): use single quotes. They are the safe choice for anything containing
$,!,`, or\. - Text that should include a variable or a command’s output: use double quotes:
echo "Backup of $HOME finished". - Always put variables that hold file names or paths in double quotes:
"$file","$HOME/My Projects". - Don’t put
~inside quotes. Use"$HOME/..."instead. - Not sure what the shell will do? Put
echoin front of the command to see the words it would receive.
20.7 Why this matters when AI writes your commands
As of Oct 6, 2026 · Official docs: How Claude Code works
Claude Code runs shell commands as part of its work (for example to run tests or use Git), and chat assistants give you commands to paste. Quotes decide what those commands actually do, so read them carefully. For example, here is the >> technique from Environment Variables, used to add a PATH line to your startup file:
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrcThe outer single quotes make everything inside literal, so the file receives exactly export PATH="$HOME/bin:$PATH", with the $ signs still in it. The variables are filled in later, each time a new terminal reads the file, which is what you want. (With outer double quotes, the inner double quotes would end the text early, and $HOME and $PATH would be filled in right away.)
Quoting rules are also one reason commands don’t move freely between shells: PowerShell and CMD on Windows quote differently from Bash and zsh. When you ask an AI for a command, say which shell you use (“zsh on a Mac” or “Git Bash on Windows”).
! and “event not found”
When you type commands interactively, Bash and zsh treat ! as a shortcut for recalling earlier commands (history expansion; for example, !! means “the previous command”). This happens even inside double quotes; only single quotes reliably protect a !.
- Git Bash:
echo "Hello!"works, because a!right before the closing quote or a space is left alone. Butecho "Wow!Great"fails withbash: !Great: event not found. - Mac (zsh):
echo "Hello!"leaves you at adquote>prompt (pressCtrl+C), andecho "Wow!Great"fails withzsh: event not found: Great. - Both:
echo 'Hello!'andecho 'Wow!Great'work.
Scripts are not affected: history expansion only happens in commands you type at the prompt. (Putting a backslash before the ! inside double quotes behaves differently in Bash and zsh, so single quotes are the simple, reliable fix.)
Practice Questions
Easy
Question 1 · True or false
Both single quotes and double quotes keep multiple spaces between words.
Question 2 · Multiple choice
In which of these commands is $HOME replaced by the path of your home directory?
echo '$HOME'echo "$HOME"echo '"$HOME"'- None of them
Question 3 · Predict the output
What does echo 'Hello $USER' print?
Question 4 · Fill in the blank
Inside ______ quotes, the shell changes nothing: every character, including $, is kept exactly as typed.
Question 5 · Multiple choice
Which command prints It's raining correctly?
echo 'It's raining'echo "It's raining"echo 'It\'s raining'echo It's raining
Medium
Question 6 · Predict the output
Sam (Git Bash, home folder /c/Users/sam) runs:
echo "My home is $HOME"
echo 'My home is $HOME'What does he see?
Question 7 · Predict the output
item="laptop"
echo "Item: $item"
echo 'Item: $item'
echo "Item: ${item}s"Question 8 · Find the bug
echo "The ticket costs $5" prints The ticket costs with no price. Why? Give two ways to fix it.
Question 9 · Write the command
Write two different echo commands that print exactly:
She said "yes"
Question 10 · Write the command
The command date +%A prints the day of the week (for example Tuesday). Use command substitution to print a line such as Today is Tuesday.
Question 11 · Find the bug
Maria types ls "~/Documents" and gets “No such file or directory”, even though her Documents folder exists. Explain, and give two commands that work.
Question 12 · Find the bug
In Git Bash, Sam types:
cd $HOME/My ProjectsHe gets an error. What’s wrong, and how should he type it?
Question 13 · Predict the output
In the notes practice folder (which contains ideas.txt and meeting-notes.txt), what do these print?
echo *.txt
echo '*.txt'Hard
Question 14 · Scenario
An AI assistant suggests this command for a commit message:
git commit -m "Update prices: now $9.99"What message will actually be saved, and how should the command be written?
Question 15 · Long answer
Explain why this command uses single quotes around the whole export ... line, and what would go wrong if you used double quotes on the outside instead.
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrcQuestion 16 · Scenario
A Bash script contains:
file="Q3 report.txt"
cat $fileIt prints two “No such file or directory” errors, although Q3 report.txt exists. Maria says the same two lines work fine when she types them into her Mac’s Terminal. Explain both observations and give the fix.
Question 17 · Scenario
On her Mac, Maria types echo "Deployment done!". The terminal shows dquote> and waits. What is going on, how does she get out, and what should she type instead?
Question 18 · Long answer
Give three rules of thumb for choosing between single quotes, double quotes, and no quotes, each with a short example.
Question 19 · Predict the output
name="Sam"
echo "Hi $name, it's \$10 for 'Pro'"