logo
NotesNotesResumeResume
© 2026 Kiet Nguyen
← All notes
Futurism Art Deco — IN OUT ERROR streams redirected into a FILE

How-to·February 10, 2026·6 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:

  1. Name stdin, stdout, and stderr and aim them with redirection.
  2. Choose >, >>, 2>, 2>&1, <, |, and /dev/null for the right job.
  3. Chain filters so each tool does one honest step.
  4. 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:

DoorFancy nameDefault destination
Inputstdin (fd 0)Keyboard
Outputstdout (fd 1)Terminal
Complaintsstderr (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.

ToolRole
catFetch / join text onto the stream
sortPut lines in order (so later tools can think)
uniqCollapse or count adjacent duplicates
grepKeep lines that match a pattern
wcCount lines/words/bytes—the scoreboard
headFirst page only
tailLast page / live ending
teePhotocopy 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

SignalYou can do this without panic
Separate streamsData in one place, errors in another
Prefer pipes over mega-commandsSolve problems as filter chains
Respect tool contractsuniq needs sorted neighbors; wc -l counts lines
Keep evidencetee a log while still watching the run
Sample huge texthead / tail before you drown
MeasureEnd 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 names
  • awk / sed — field surgery and stream edits
  • xargs — lines into command arguments (carefully)
  • Shell discipline — quoting, "$@", set -o pipefail so 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 grep only wants the lines that matter.

Back to notes

Was this page helpful?