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

$ ls notes.txt nope.txtEXIT 1
·notes.txt
ls: nope.txt: No such file or directorystderr → screen
|

grep keeps 0 of 1 line

1 dropped

× notes.txt

errors skip the pipe and go to the screen

$ grep nopeOUTPUT

no output

Tap any part of the command to see what it does

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

$ ls notes.txt nope.txtEXIT 1
·notes.txt
›ls: nope.txt: No such file or directorystderr
|

grep keeps 1 of 2 lines

1 dropped

× notes.txt

$ grep nopeOUTPUT
ls: nope.txt: No such file or directory
Tap any part of the command to see what it does

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 -l

The error line is counted: prints 1.

$ make > build.log 2>&1

Save output and errors in one file.

$ ls nope.txt 2>/dev/null

Throw 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.