Public beta. We're in our soft launch: the lessons are ready, but things may still change, and your feedback shapes what comes next.

Linux Basics 2 · Lesson 2 · 25 min

Wildcards & your first pipes

Typing twelve file names is boring. Typing *.jpg isn't. Wildcards let one short pattern stand for many files, and brace expansion writes long lists for you. Then the pipe | joins small commands into bigger ones. Together they turn ten minutes of clicking into one line.

You will learn

  • The wildcards *, ? and [ ], and why they skip hidden files
  • Brace expansion: {a,b,c} and {1..10}
  • Previewing with echo before a risky rm
  • Quotes, and when to stop the shell from expanding things
  • Your first pipes: | wc -l, | grep, | sort, | head

The shell expands them, not the command

When you type ls *.jpg, ls never sees the star. bash looks at the files first, replaces *.jpg with the matching names, and then runs ls IMG_0001.jpg IMG_0002.jpg …. That's why the same patterns work with every command: cp, mv, rm, tar, anything.

PatternMatchesExample
*any number of any characters (even none)*.log, IMG_*, *2026*
?exactly one characterIMG_000?.jpg (0001 to 0009)
[abc]one character from the list[abc]* (names starting with a, b or c)
[0-9]one character from a rangeapp-2026-09-0[1-5].log
[!0-9]one character NOT in the list[!.]*

Brace expansion: lists without typing

mkdir -p project/{src,docs,tests}          # three folders
touch project/src/file{1..3}.py            # file1.py file2.py file3.py
echo {a..e}                                 # a b c d e
cp config.yml{,.bak}                        # cp config.yml config.yml.bak

Braces are different from wildcards: they make names whether or not the files exist. Wildcards only match files that are already there.

Look before you leap: echo first

echo rm logs/app-2026-09-0[1-3].log    # shows exactly what would be deleted
rm logs/app-2026-09-0[1-3].log         # same line without "echo"
The most expensive space in computing

rm -rf /tmp/old * (with a space before the star) deletes everything in your current folder, and so does rm *.txt with a typo like rm * .txt. Put echo in front of any rm with a wildcard, read what it prints, then remove the echo.

Quotes switch expansion off

echo *.txt          # the names of your .txt files
echo '*.txt'        # literally: *.txt
find . -name '*.png'   # quotes: find does the matching, in every subfolder
ls "screenshot 1.png"  # quotes keep a name with a space as ONE argument

With find -name you want the pattern to reach find, so quote it. Otherwise bash expands it in the current folder first, and find gets the wrong question.

Your first pipes

A pipe sends one command's output into the next command's input. Small tools, snapped together:

ls photos | wc -l                         # how many files?
ls logs | grep error                      # only names containing "error"
ls logs | sort -r | head -3               # the three newest dated logs
ls -l photos/*.jpg | sort -k5 -n | tail -1   # the biggest jpg (column 5 = size)

The Linux Sysadmin path goes much further (redirection, awk, cut, uniq…), but these four will carry you a long way: Linux Sysadmin, lesson 3.

Practice: sort out the photos 📸

You have a photos folder (and one sneaky hidden file) and a logs folder with a log per day. Find things with wildcards, build a project folder with braces, delete old logs safely, and count things with pipes.

Quick check

1. Which files does report-0?.txt match?

2. Why doesn't ls * show .bashrc?

3. What's the safe habit before rm logs/*2025*?

Finished the missions and the quiz? Mark it done to track your progress.

Send feedback

We're in a public beta, so every message helps. What's on your mind?

Please don't include your name, email or other personal details. We can't reply, but we read every one. We'll note which page you sent it from.