Shell, explained
What does 2>&1 mean?
ls notes.txt nope.txt 2>&1 | grep nope
2>&1 sends a command's error output (stream 2, stderr) to the same place as its normal output (stream 1, stdout). Without it, errors skip the pipe and go straight to your screen, so the next command never sees them.
Without 2>&1, the error skips the pipe
ls prints notes.txt on stdout and the error on stderr. Only stdout goes down the pipe, so grep never sees the line it is looking for, while the error still shows up on screen.
Tap a part of the command to find it below
grep keeps 0 of 1 line
× notes.txt
errors skip the pipe and go to the screen
no output
With 2>&1, grep sees the error too
2>&1 points stderr at the pipe as well, so both lines reach grep and it finds the error.
Tap a part of the command to find it below
grep keeps 1 of 2 lines
× notes.txt
Part by part
ls notes.txt nope.txt- Lists two files. One does not exist, so ls prints an error for it.
2>- Redirects stream 2, the error output (stderr).
&1- …to wherever stream 1 (stdout) is going. The & says “a stream number”, not a file called 1.
|- Sends stdout, which now carries the errors too, into grep.
grep nope- Keeps the lines that contain nope: here, the error message.
Common mistakes
Putting 2>&1 before > file
cmd > out.txt 2>&1 saves both streams in out.txt. cmd 2>&1 > out.txt does not: 2>&1 copies where stdout points at that moment (your screen), and only then is stdout moved to the file.
Writing 2>1
Without the &, 2>1 sends errors into a file named 1 in the current folder.
Try it
$ ls nope.txt 2>&1 | wc -lThe error line is counted: prints 1.
$ make > build.log 2>&1Save output and errors in one file.
$ ls nope.txt 2>/dev/nullThrow the errors away instead.
Questions
Why &1 and not just 1?
After >, a plain word is a file name. &1 tells the shell you mean stream number 1, not a file called 1.
Is there a shorter way?
In zsh and bash 4+, |& is short for 2>&1 |. In bash and zsh, &> file is short for > file 2>&1. In plain sh (and the bash 3.2 macOS ships), stick to the long form.
What are streams 0, 1 and 2?
Every program starts with three: 0 is standard input (what it reads), 1 is standard output (normal results) and 2 is standard error (problems and progress messages).
Terminaster
Ask about any command and get a picture like this one.
The Terminaster tutor draws these visuals for your own questions, then turns what you learned into spaced-repetition cards so it sticks.
The ideas behind it
Standard input, output, and error
A command-line process normally starts with three conventional open streams: standard input for incoming data, standard output for primary results, and standard error for diagnostics.
File descriptor
A file descriptor is a non-negative integer that indexes an entry in one process's descriptor table. That entry refers to a kernel-managed open resource such as a file, pipe, socket, terminal, or device.
Redirection
Redirection is shell syntax that opens, closes, or duplicates file descriptors for a command before that command begins executing.