>_How the Terminal Works · Lesson 3 of 7

stdin, stdout & Pipes

Every program is born holding three data streams: input, output, errors. Redirection and pipes just re-plug those streams — into files, or into other programs. This is the terminal's superpower.

Bash
# Three standard streams, by number:
#   0 stdin  — bytes in (default: your keyboard)
#   1 stdout — results out (default: your screen)
#   2 stderr — errors out (default: also your screen)

ls > files.txt        # stdout -> file (overwrite)
ls >> files.txt       # stdout -> file (append)
ls /nope 2> err.txt   # stderr -> file
ls /nope > all.txt 2>&1   # both -> one file
sort < names.txt      # file -> stdin

# stderr is separate ON PURPOSE — errors stay visible
# even when you redirect the results:
myprogram > results.txt     # errors still hit your screen

The pipe | connects one program's stdout to the next one's stdin, no temp files involved. Both programs run simultaneously; the kernel shuttles bytes between them and pauses the fast one when the slow one falls behind. Small tools, each doing one job, snapped together like hose segments — the Unix philosophy in one character.

Bash
# Build analysis pipelines out of small tools:
history | grep git | wc -l       # how many git commands you've run

# Classic shape: extract | filter | transform | count
cat access.log \
  | grep " 500 "        \
  | awk '{print $1}'    \
  | sort | uniq -c      \
  | sort -rn | head     # top IPs causing server errors

# tee splits a stream: to a file AND onward
long_build 2>&1 | tee build.log | grep -i error
◆ Note
Programs adapt to where their output goes: ls prints columns to a terminal but one-name-per-line into a pipe (it checks 'is stdout a TTY?'). Same reason color codes vanish when you redirect to a file — well-behaved tools only emit them for real terminals.