Learn › Linux Foundations › Bash Shell Environment
echo - a hands-on Linux lab on a real virtual machine.
The rule that ties the Bash Environment module together: three quoting modes. Single quotes switch off all expansion (everything literal), double quotes expand $ and $() but protect spaces and wildcards, and the backslash escapes one character. Learn why "$var" is the safe default, meet the continuation prompt, and the single-quote-inside-single-quotes trap.
Here is a puzzle that trips up almost everyone the first week. You have a word saved in the shell, the name alice, and you ask the shell to print it. You type it two ways that look nearly identical, and you get two completely different results.
One way prints alice. The other prints $name. Same three letters of difference: a pair of quotes. By the end of this lesson you will know exactly which quotes do what, and you will never guess again.
The black boxes in this lesson are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. Before any of the drills, imagine we already ran name=alice in this shell. That sets a variable called name holding the text alice. Every box below assumes that is already done, so $name means alice throughout.
Quoting is how you tell the shell which special characters to take seriously and which to treat as plain text. That is the entire idea.
The shell is not a dumb pipe. Before it runs your command, it scans what you typed and does work on it: it swaps $name for the variable's value, it splits your line on spaces into separate words, and it expands wildcards like * into matching filenames. This scanning is called expansion. Quoting is the steering wheel for expansion. There are three ways to steer: single quotes, double quotes, and the backslash. This one rule ties the whole Bash Environment module together.
A quick word on echo. echo simply prints whatever arguments the shell hands it, separated by single spaces. That makes it the perfect microscope for quoting: whatever echo prints is exactly what the shell decided to pass along after expansion. So all lesson we watch echo to SEE what quoting did.
Start with the bare form, no quotes at all. When you write $name unquoted, the shell finds the variable and swaps in its value before echo ever runs. echo never sees $name; it sees alice.
Before you run it, commit to an answer: with name holding alice, what does the shell hand to echo? Type it and see:
prompt: student@linuxcamp:~$ answer: echo $name output: alice hint: Type echo, a space, then a dollar sign stuck to the word name: echo $name
The shell saw $name, looked it up, replaced it with alice, and only then ran echo alice. That is expansion doing its job. Unquoted $name is the shell reaching into the variable and pouring its value onto the command line. Useful, and most of the time exactly what you want. But the same eager expansion has a sharp edge, which the next step exposes.
Now wrap the exact same text in single quotes. Single quotes are the OFF switch for expansion. Everything between them is passed through untouched, character for character. The dollar sign is no longer special; it is just a dollar sign.
Commit first: you already saw echo $name print alice. What will echo '$name' print, now that the single quotes turn expansion off?
prompt: student@linuxcamp:~$ answer: echo '$name' output: $name hint: Wrap dollar-sign-name in single quotes, the key next to Enter: echo '$name'
This is the delta that teaches the whole lesson. Same characters inside, $name, but the single quotes told the shell to do NO expansion, so echo received the literal text $name and printed it exactly. No lookup, no swap. Single quotes mean what you see is what you get. That is why they are the tool for text you want kept EXACTLY as written: a literal dollar sign, a regular expression, a password with special characters in it.
So single quotes kill expansion and no quotes allow it. Double quotes are the useful middle ground, and they are the ones you will reach for most. Double quotes still ALLOW $variable and $(command) expansion, so $name still becomes alice. What they add is protection: everything inside stays glued into one single word.
First confirm the expansion still happens. Same variable, this time in double quotes:
prompt: student@linuxcamp:~$ answer: echo "$name" output: alice hint: Wrap dollar-name in double quotes this time, the key above Enter with Shift: echo "$name"
Notice echo "$name" still printed alice, exactly like the bare echo $name did. That is the point: double quotes did NOT switch off the variable. So why bother with them at all? Because of the OTHER thing the shell does to an unquoted line: it splits on spaces. The next step shows why that matters.
Here is the whole reason double quotes exist. Hand echo a run of text with several spaces in it and watch what quoting does to those spaces.
Without quotes, the shell would chop that run into words and collapse every gap to a single space. Inside double quotes, the spaces are protected, so the text arrives as ONE piece, gaps and all:
prompt: student@linuxcamp:~$ answer: echo "hello world" output: hello world hint: Put the whole phrase, spaces and all, inside double quotes: echo "hello world"
Run that same phrase with NO quotes, echo hello world, and the shell splits it into two words, hello and world, then rejoins them with a single space, so you get hello world with the gap gone. The quotes are what preserved the three spaces. This is not a party trick: it is exactly what protects a variable that holds a value with spaces in it, which is the next honest danger.
Put the two ideas together and you get the single most important quoting habit in Linux. A variable might hold a value with spaces, for example a file name like My Notes.txt. If you use it unquoted, the shell expands it AND then splits it on those spaces, so a name meant to be one thing arrives as two separate arguments.
That is where you meet a classic error. Say a variable file holds My Notes.txt and you run a command on $file unquoted. The shell splits it, and the command tries to open two things that do not exist:
prompt: student@linuxcamp:~$ answer: echo $file output: My Notes.txt hint: Just echo the variable with no quotes to watch the shell hand over the pieces: echo $file
Through echo the split looks harmless, because echo prints all its arguments with a space between them, so My, Notes.txt comes back out looking like My Notes.txt. The damage shows with a real command. cat $file unquoted becomes cat My Notes.txt, two arguments, and cat answers with the classic:
cat: My: No such file or directory cat: Notes.txt: No such file or directory
Two errors from one file, because the unquoted split turned one name into two. What to check first when you see that: did you forget the double quotes around a variable that holds spaces? The fix is cat "$file". That is why "$var", in double quotes, is the safe default for variables.
Quotes protect a whole run of text. Sometimes you only need to protect ONE character. That is the backslash, \. A backslash tells the shell to take the very next character literally and nothing more. It is a single-character version of single quotes.
Put a backslash before a dollar sign and the shell stops treating it as the start of a variable. Commit first: you know echo $name prints alice. What does echo \$name print, with the dollar sign escaped?
prompt: student@linuxcamp:~$ answer: echo \$name output: $name hint: Put one backslash right before the dollar sign: echo \$name
The backslash disarmed just the $, so echo received the literal $name and printed it, the same result single quotes gave you. The backslash also works on a space: echo a\ b keeps the space by escaping it, so the two words arrive as one. Reach for the backslash when you need ONE literal special character in a line that otherwise expands normally. For a whole stretch of literal text, single quotes are cleaner.
One quoting mistake looks like the shell froze, and it panics beginners every time. You open a quote, press Enter before closing it, and instead of your usual prompt you get a lonely > on the next line. The shell has not crashed. It is telling you the quote is still open and it is waiting for you to finish it.
That single > is the continuation prompt. The shell saw an opening quote with no matching close, so it assumes your command runs onto the next line and asks for the rest. Here is what an unterminated double quote looks like:
When you see a bare > and you did not mean to be there, do not keep typing wild guesses. Either close the quote you opened, a single " or ' and Enter, or press Ctrl-C to throw the line away and get a clean prompt back. Ctrl-C is your escape hatch for any half-typed line.
There is one thing single quotes cannot do: hold a single quote. Because a single quote turns expansion OFF until the very next single quote, the shell reads the second one as the CLOSING quote, not as text. So you cannot simply put an apostrophe inside a single-quoted word, for example the word don't.
The fix engineers use is to break out, add an escaped quote, and dive back in: 'don'\''t'. Read it in pieces: 'don' is the first quoted chunk, \' is one literal escaped apostrophe outside the quotes, and 't' is the second quoted chunk. The shell glues those three touching pieces into one word, don't.
That pattern looks alien the first time, and that is fine. You rarely need it. The takeaway is the rule behind it: a single-quoted string ends at the next single quote, no exceptions, so a literal apostrophe has to live OUTSIDE the single quotes, escaped with a backslash or wrapped in double quotes instead. When you just want an apostrophe in text, double quotes are usually the easier choice: echo "don't" prints don't with no gymnastics.
Scaffolding off. No command is shown this time. You have every piece you need.
The variable name still holds alice. But you do not want its value. You want the shell to print the four literal characters $name on screen, dollar sign and all, with expansion switched off. Reach for the mode built for keeping text exactly as written.
prompt: student@linuxcamp:~$ answer: echo '$name' output: $name hint: You want NO expansion at all, every character literal. Which quote is the off switch? Wrap $name in it.
Single quotes were the answer, because you wanted zero expansion: the dollar sign kept literal, the text exactly as typed. echo "$name" would have betrayed you here and printed alice, and echo $name too. The backslash form echo \$name also works and prints the same $name, so if you reached for that, you were right as well. Any route that switches off the $ earns the point. You recalled the off switch from memory, which is the same recall the real machine will ask of you.
You earned this cheat sheet. This is the rule to memorise, and every row you just ran yourself (with name holding alice):
The one rule under all of it: single quotes = everything literal, no expansion. Double quotes = expand $ and $() but protect spaces and wildcards. No quotes = expand variables AND split on spaces AND expand wildcards. And the habit that flows from it: "$var" in double quotes is the safe default for any variable, because it expands the value while shielding it from being split on spaces.
A one-line way to remember which to grab: if the text should come out EXACTLY as typed, use single quotes. If you need a variable's value but also safety, use double quotes. If you only need to tame one stray special character, use a backslash.
The practice terminal has shown you all three modes of quoting. You watched an unquoted variable expand, single quotes shut expansion off, double quotes expand while protecting spaces, and the backslash escape a single character. You met the > continuation prompt and the single-quote-inside-single-quotes trap. Every one of those you typed yourself.
The Bash Environment module ends with one real Linux machine, the Bash Environment capstone mission, and that is where quoting stops being a drill and starts protecting real files. A VM boots just for you, with its own shell. It hands you objectives that use exactly what you practiced across this module: variables, the environment, $PATH, aliases, expansions, and the quoting rules that keep them all from breaking on a space. One difference from here: the mission shows no commands. You read the objective, you recall the quoting mode, you type it. That recall is what makes it stick.
Finish the other Bash Environment lessons, then go quote for real.
Practice Quoting in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.