Shell FluencyLesson 3 of 4
Globbing, expansion and quoting
Know exactly what the shell rewrites before a command runs, and quote to stop it when you must.
echo'*'{}$()aliashistoryexportenv
After this lesson you can
- Use wildcards and brace expansion to name many files at once.
- Choose between no quotes, double quotes and single quotes on purpose.
- Use variables, command substitution, history and aliases to work faster and make settings persistent.
The idea
Before bash runs a command it rewrites the line. This is called expansion, and it happens in a fixed order: braces, then ~ and $variables, then $(commands), then globs (wildcards) against real file names. The command never sees your wildcard; it sees the finished list. That is why echo *.txt shows you what rm *.txt would delete.
| Pattern | Matches |
|---|---|
* | Any run of characters, including none |
? | Exactly one character |
[abc], [a-c] | One character from the set or range |
{a,b,c} | Brace expansion: three words, even if no such files exist |
~, ~bob | Your home, or bob’s home |
Quoting stops expansion. Double quotes keep $variable and $(command) working but stop word-splitting and globbing. Single quotes stop everything. A backslash quotes the next character. When in doubt, quote a variable: "$file".
Try it
mkdir -p ~/lab/glob && cd ~/lab/glob
touch a.txt b.txt c.log
echo *.txt
echo ?.log
echo [ab].*
a.txt b.txt
c.log
a.txt b.txt
echo report-{jan,feb,mar}.txt
report-jan.txt report-feb.txt report-mar.txt
name="Linux Lab"
echo "Hello $name"
echo 'Hello $name'
echo "Today is $(date +%A)"
Hello Linux Lab
Hello $name
Today is Tuesday
Variables and the environment
A plain variable (name=value) lives only in this shell. export copies it into the environment of every command you start. PATH is the list of directories searched for commands, and env prints what child programs will inherit.
echo $PATH
export PATH="$HOME/bin:$PATH"
echo $PATH
/home/alex/.local/bin:/home/alex/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
/home/alex/bin:/home/alex/.local/bin:/home/alex/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
History and keyboard speed
history | tail -3
101 echo "Today is $(date +%A)"
102 echo $PATH
103 history | tail -3
!! repeats the last command, !string the last one that started with string, Ctrl+R searches backwards, Tab completes names and Ctrl+C stops a running command.
Going further
Use alias name='command' for shortcuts and unalias name to remove one. \ls bypasses an alias for one run. When a wildcard matches nothing, bash passes the pattern through unchanged, so rm *.bak with no .bak files tries to remove a file literally named *.bak. Look first with echo, delete second.
Practice
0 of 5 done
Do these on your own system. They get harder. Check each result, then tick it off.
- Warm-up
Watch the shell rewrite your line
In an empty
~/lab/globdirectory createa.txt b.txt c.log. Useecho(notls) to show which names.txt,?.logand[ab].expand to.Check your result
The three
echolines printa.txt b.txt,c.loganda.txt b.txtin that order.Hint
echoprints whatever the shell hands it, so it shows the expansion.Solution
mkdir -p ~/lab/glob && cd ~/lab/glob touch a.txt b.txt c.log echo *.txt echo ?.log echo [ab].* - Practice
Build a tree in one command
With one
mkdircommand, create~/lab/proj/src,~/lab/proj/testsand, insidedocs, directories2025and2026. Print the directories withfind.Check your result
find ~/lab/proj -type d | sortlistsproj,docs,docs/2025,docs/2026,srcandtests.Hint
Braces can nest:
proj/{src,tests,docs/{2025,2026}}. Add-pso parents are created.Solution
mkdir -p ~/lab/proj/{src,tests,docs/{2025,2026}} find ~/lab/proj -type d | sort - Practice
Three kinds of quote
Set
nametoLinux Lab(it has a space). PrintHello $namewith no quotes, with double quotes and with single quotes around the whole text. Describe the three results.Check your result
Double quotes expand
$nameand keep it as one word:Hello Linux Lab. Single quotes printHello $nameliterally. Without quotes the shell expands$nameand then splits it into two words, whichechoprints with a single space.Hint
Assignments need quotes around values with spaces, and no spaces around
=.Solution
name="Linux Lab" echo Hello $name echo "Hello $name" echo 'Hello $name' - Practice
Put one command's output inside another
Create a file in
~/labwhose name contains today's date inYYYY-MM-DDform, for examplereport-2026-11-03.txt, and put the host name inside it. Do not type the date.Check your result
ls ~/lab/report-*.txtshows one file andcatprints the host name.Hint
date +%Fprints the date. Wrap a command in$( )to use its output.Solution
hostname > ~/lab/report-$(date +%F).txt ls ~/lab/report-*.txt cat ~/lab/report-*.txt - Challenge
Make a shortcut survive logout
Make two settings available in every new login shell of your user: an alias
ll2forls -lAh --group-directories-first, and~/binat the front ofPATH. Prove it from a brand-new login shell, and say which files bash reads.Check your result
Running
bash -lc 'type ll2; echo $PATH'prints the alias definition and a path that starts with/home/alex/bin.Hint
Per-user settings go in
~/.bashrc. Login shells read~/.bash_profile, which on RHEL loads.bashrc.Solution
mkdir -p ~/bin echo "alias ll2='ls -lAh --group-directories-first'" >> ~/.bashrc echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc bash -lc 'type ll2; echo $PATH'