Pipes & redirection
stdin, stdout and stderr, >, >>, 2>&1, pipes, tee, xargs and command substitution.
The Unix philosophy is "write programs that do one thing well, and work together". The glue that makes them work together is redirection (connect a command to files) and pipes (connect commands to each other). Once these click, you'll be building one-line tools that would take a page of code elsewhere.
The three standard streams#
Every process starts with three open "files", known by number (file descriptors):
Both stdout and stderr appear on your screen, but they are separate streams. That's why you can save results to a file and still see errors.
Redirecting output: > and >>#
⚠️
>truncates the file before the command even runs.sort data.txt > data.txtleaves you with an empty file! Write to a new file, or usesort -o data.txt data.txt(orspongefrommoreutils).
Turn on set -o noclobber to make > refuse to overwrite existing files (>| forces it).
Redirecting errors: 2>#
Common patterns:
/dev/null is the "black hole" device: anything written to it disappears, and reading from it gives an immediate end-of-file.
Order matters. cmd > file 2>&1 sends both to the file. cmd 2>&1 > file first points stderr at the terminal (where stdout currently goes) and only then moves stdout to the file, so errors still appear on screen.
Redirecting input: <, here-docs and here-strings#
A here-document (<<WORD ... WORD) feeds several lines to a command, which is great for writing config files from scripts. Variables and $(...) are expanded inside it; quote the marker (<<'EOF') to keep the text literal. Use <<-EOF to strip leading tabs so you can indent it inside scripts.
Pipes: connecting commands#
A pipe | connects the stdout of one command to the stdin of the next:
Read it left to right: list, sort (so duplicates are adjacent), count duplicates, sort by count descending. All the commands in a pipeline run at the same time, streaming data, so pipelines work on files far bigger than memory.
A few classic pipelines:
Only stdout goes through a pipe. To pipe errors too, use 2>&1 | or the bash shorthand |&:
tee: save and see#
tee writes its input to a file and passes it on:
tee also solves the classic sudo redirection problem. In sudo echo x > /etc/file, the redirection is done by your shell, which isn't root. Instead:
Command substitution: $( )#
$(command) runs a command and inserts its output into another command line:
You'll see old scripts use backticks `date`. They do the same job, but $( ) nests cleanly and is easier to read.
xargs: turn input into arguments#
Some commands don't read stdin; they want arguments (rm, mkdir, cp...). xargs reads items from stdin and passes them as arguments:
-n 1runs the command once per item.-I {}lets you place the item anywhere:xargs -I {} cp {} {}.bak.-P 4runs up to 4 commands in parallel.-print0/-0separate items with NUL bytes, so filenames with spaces or newlines are safe. Always use this pair withfind.
Exit codes and chaining#
Every command finishes with an exit status: 0 means success, anything else is failure. $? holds the last one:
A pipeline's exit status is the last command's, so false | true succeeds. In scripts, set -o pipefail makes a pipeline fail if any part fails (covered in the scripting module).
Process substitution (bash)#
<(command) makes a command's output look like a file, which is handy for tools that want filenames:
Common mistakes#
cmd > fileon the file you're reading: the file is truncated before reading starts.2>&1in the wrong place:cmd 2>&1 > filestill prints errors to the screen.sudo cmd > /root-owned/file: use| sudo tee file.- Parsing
lsoutput in pipelines: filenames with spaces break it. Use globs orfind -print0 | xargs -0. - Useless
cat:cat file | grep xworks, butgrep x fileis simpler. That's harmless, but good to know. - Forgetting that pipes carry only stdout: add
2>&1(or|&) if you need errors too.
What's next#
Pipes are most powerful with good filters. Next comes text processing: cut, sort, uniq, tr, wc, paste and friends.
Check your understanding
Quick quiz
1.What does
command > out.txt 2>&1do?2.Which command shows output on screen AND saves it to a file?
3.Why does
sudo echo 'x' > /etc/myfilefail with Permission denied?
Finished reading?
Mark this lesson complete to track your progress.