
How-to6 min read
The art of redirection
Linux · Shell · Bash · Learning
Learn shell redirection and filters: >, >>, 2>, <, |, plus cat, sort, uniq, grep, wc, head, tail, and tee—so the terminal becomes a workshop of streams, not a vending machine.
I used to treat the terminal like a vending machine: type a command, get a snack on the screen, walk away. Then I met redirection—and suddenly the snack could go in a box, into another machine, or into a box and my mouth at the same time (tee is basically that party trick).
This how-to maps a leveling-up path: first the plumbing (>, >>, 2>, <, |), then the small tools that make pipelines powerful—cat, sort, uniq, grep, wc, head, tail, tee.
What you will learn
By the end you should be able to:
- Name stdin, stdout, and stderr and aim them with redirection.
- Choose
>,>>,2>,2>&1,<,|, and/dev/nullfor the right job. - Chain filters so each tool does one honest step.
- Run a short practice loop and explain why each stage exists.
Level 0 — Before redirection, only a screen
Every process walks around with three open doors:
| Door | Fancy name | Default destination |
|---|---|---|
| Input | stdin (fd 0) | Keyboard |
| Output | stdout (fd 1) | Terminal |
| Complaints | stderr (fd 2) | Terminal (same room, different mood) |
Without redirection, stdout and stderr both show up in your face like two friends talking at once. With redirection, you become a stage manager: “You, quiet log file. You, errors only. You, go talk to grep.”
That picture—three streams, not one blob of “output”—is the first real level-up.
Level 1 — Redirection plumbing
> — Put the success story in a file (overwrite)
ls -la > listing.txt
Think of > as: the shell opens the file first, empties it, then attaches stdout there.
Running it twice means the first draft is gone. That is not the computer being mean; that is hiring a clean whiteboard.
>> — Append; keep the diary going
date >> lab-diary.txt
echo "still experimenting" >> lab-diary.txt
Same door (stdout), kinder personality. Session notes and append-only logs love >>.
2> — Errors get their own notebook
find /etc -name '*.conf' 2> find-errors.txt
Stdout can stay on screen (or go elsewhere); stderr goes to a file. When something fails, read the complaint department instead of yelling at the happy output.
2>&1 — Merge the group chat
make 2>&1 | tee build.log
# or
make > build.log 2>&1
Order matters a little—like seating arrangements. Classic pattern: send stdout to a file, then send stderr to wherever stdout is going now.
< — Read the file as if you typed it
sort < names.txt
wc -l < /etc/passwd
Some tools take a filename; some prefer stdin. < plugs a file into the input hose.
| — Hand the stream to the next craftsperson
ls /usr/bin | wc -l
This is when the shell stops being a vending machine and becomes a workshop assembly line. No temporary middle file required (unless you want one).
/dev/null — The polite black hole
command > /dev/null 2>&1
Not evil. Output goes here when you only care about exit status—or when a tool is chatty and you already know the plot.
Level 2 — Why small tools beat one giant spell
Once | clicks, stop looking for a single command that “does the whole investigation.” Look for filters: programs that read text in, write text out, and do one job well enough to chain.
| Tool | Role |
|---|---|
cat | Fetch / join text onto the stream |
sort | Put lines in order (so later tools can think) |
uniq | Collapse or count adjacent duplicates |
grep | Keep lines that match a pattern |
wc | Count lines/words/bytes—the scoreboard |
head | First page only |
tail | Last page / live ending |
tee | Photocopy the stream while it still flows |
Redirection without filters is plumbing with no sinks. Filters without redirection are sinks in a desert. Together they are the workshop.
Level 3 — The crew, one tool at a time
cat — Concatenate (or pour a file into the pipe)
cat notes.txt
cat part1.txt part2.txt > combined.txt
cat header.txt body.txt footer.txt | wc -l
Use cat to concatenate and to start a stream. For long files, prefer a pager (less).
sort — Sort lines
sort names.txt
sort -n numbers.txt # numeric-ish sort when you need it
ls | sort
Many later tricks assume order. Without sort, uniq misunderstands you.
uniq — Report or omit repeated lines
sort names.txt | uniq
sort names.txt | uniq -c # count each run of duplicates
sort names.txt | uniq -d # only lines that had duplicates
uniq only collapses neighbors. Unsorted duplicates on opposite ends of the file stay. Almost always:
… | sort | uniq
grep — Lines matching a pattern
grep error app.log
grep -i error app.log # case-insensitive
grep -n pattern file # line numbers
grep -v noise file # invert: drop matching lines
ps aux | grep ssh
Pattern in, matching lines out—ready for the next pipe. Flags grow over time; the core contract stays.
wc — Counts
wc file.txt
wc -l file.txt # lines only—daily driver
ls /usr/bin | wc -l
grep -i error app.log | wc -l
Turns vibes into numbers: “many failures” becomes “37 matching lines.”
head — First part of a file
head file.txt # first 10 lines by default
head -n 20 file.txt
ls -t | head -n 5
Huge file? Opening credits only. After sort, “top of the list” without the whole epic.
tail — Last part (or follow)
tail file.txt
tail -n 50 file.txt
tail -f app.log # follow: watch new lines arrive
tail -f is a polite vigil on a log without reopening the file forever.
tee — stdin → stdout and file(s)
make 2>&1 | tee build.log
make 2>&1 | tee -a build.log | tail -n 20
Save the stream and keep piping. History and liveness in one move.
Level 4 — Combos worth reusing
# How many unique lines?
ls | sort | uniq | wc -l
# Matching lines, counted
grep -i error app.log | wc -l
# First look at a sorted unique list
sort data.txt | uniq | head
# Save a filtered slice while counting
grep -i fail app.log | tee fails.txt | wc -l
# Capture a build log while watching it
make 2>&1 | tee build.log
Each stage is simple. The art is order—sort before uniq, grep before wc when you only want a subset, tee when future-you deserves a file.
Level 5 — Checklist: redirection as posture
| Signal | You can do this without panic |
|---|---|
| Separate streams | Data in one place, errors in another |
| Prefer pipes over mega-commands | Solve problems as filter chains |
| Respect tool contracts | uniq needs sorted neighbors; wc -l counts lines |
| Keep evidence | tee a log while still watching the run |
| Sample huge text | head / tail before you drown |
| Measure | End with a number when a number helps |
Level 6 — Natural next doors (not homework)
When redirection and these filters feel friendly:
- More
grep— regex, context (-A/-B), recursive search find+ pipes — locate files, then filter namesawk/sed— field surgery and stream editsxargs— lines into command arguments (carefully)- Shell discipline — quoting,
"$@",set -o pipefailso pipelines report honest failure
You do not need all of that on day one. Redirection plus the eight tools above already unlock most daily stream work.
Practice loop
# 1) Capture
printf 'b\na\na\nc\nb\n' > sample.txt
# 2) Organize + dedupe + count
sort sample.txt | uniq -c
# 3) Hunt
grep a sample.txt
# 4) Measure
wc -l sample.txt
# 5) Edges
head -n 2 sample.txt
tail -n 2 sample.txt
# 6) Save and show
sort sample.txt | uniq | tee unique.txt | cat
If you can narrate why each step exists, you are not only memorizing flags—you are practicing the art.
Closing
Redirection teaches that the shell has plumbing.
cat through tee teach that the shell has a workshop.
Flags still get looked up (humans do that). What changes is the default move: when there is too much text, aim a pipe, invite a filter, and let small tools do small honest jobs in sequence.
stdout goes there, stderr goes there, and
greponly wants the lines that matter.
Was this page helpful?