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.