Pipes & Redirection

Pipes chain commands together so one program's output becomes the next program's input — the idea that makes small, single-purpose Unix tools genuinely powerful when combined.

The pipe operator

| sends one command's standard output directly into the next command's standard input:

$ terminal
cat access.log | grep "ERROR" | wc -l
Terminal output
7

This chain reads access.log, keeps only lines containing "ERROR", and counts how many lines are left — three small tools combining to answer "how many error lines are there?" without any of them needing to know about the others.

Redirecting stderr separately

Bash keeps standard output (1) and standard error (2) as separate streams, and you can redirect each independently:

$ terminal
./backup.sh > success.log 2> errors.log

Normal output goes to success.log; anything the script writes to stderr (typically error messages) goes to errors.log instead — keeping the two from getting mixed together in one file. &> both.log sends both streams to the same file if you want them combined.

Chaining with && and ||

&& runs the next command only if the previous one succeeded; || runs the next command only if the previous one failed:

$ terminal
mkdir backups && echo "Folder created"
cp missing.txt backups/ || echo "Copy failed, file not found"
Terminal output
Folder created
Copy failed, file not found
Note: each stage of a pipeline runs in its own subshell. That means a variable set inside a pipeline — like a counter incremented inside cat file | while read line; do count=$((count+1)); done — disappears once the pipeline finishes; the count outside the pipe never sees the updates. If you need the result outside the pipe, avoid piping into the loop (redirect from the file with < instead, as in the previous lesson) or capture the final value some other way.