Right, so you’ve mastered the art of throwing standard output (stdout) into a file with a simple >. Feels good, doesn’t it? You run a command, it does its thing, and you get a nice, clean log file. Then you run something that blows up spectacularly, you check your beautiful log file, and… it’s empty. The crushing silence of a command that failed without a trace. All those glorious, helpful error messages went straight to the bit bucket in the sky because you forgot about stderr.

Welcome to the second, far more temperamental stream: standard error. By design, it’s kept separate from stdout so that error messages can be displayed to you, the human, even if the regular output is being redirected to a file or another program. It’s a good idea, until you actually want to capture those errors. That’s where 2> and the wonderfully terse 2>&1 come in.

The File Descriptor is the Key

To understand this, you need to know the magic numbers. The shell gives everything a number, a file descriptor.

  • 0 is stdin
  • 1 is stdout
  • 2 is stderr

When you use >, you’re actually using a shortcut. The command ls > file.txt is really ls 1> file.txt under the hood. The 1 is implied. So 2> simply means “redirect file descriptor #2 (stderr) to this file.”

Let’s break something on purpose to see it work.

# This will generate an error (unless you have a directory named 'fictional_dir')
$ ls -la fictional_dir > output.txt
ls: cannot access 'fictional_dir': No such file or directory

The error printed on my screen, but let’s see what’s in output.txt. Nothing. The stdout was successfully redirected to the file, and since there was no stdout (the command failed), the file is empty. The stderr was left alone to yell at me.

Now, let’s catch that yell in a file:

$ ls -la fictional_dir 2> errors.txt
# No output to the screen! The error went to the file.
$ cat errors.txt
ls: cannot access 'fictional_dir': No such file or directory

Perfect. Now we’re capturing the mess for later review.

The “And Now, For My Next Trick” Operator: 2>&1

But what if you want both stdout and stderr in the same file? This is where everyone’s brain short-circuits the first time they see it. You might try this:

# This does NOT work as you might expect!
$ ls -la fictional_dir real_file.txt > combined.txt 2> combined.txt

Don’t do this. You’re telling the shell to open the same file twice, and the two streams will fight over it, leading to interleaved and garbled output. It’s a race condition in a can.

The correct incantation is 2>&1. This doesn’t mean “redirect stderr to a file named &1.” That would be too logical. The & indicates that what follows is a file descriptor, not a filename. So 2>&1 means “make file descriptor #2 (stderr) point to the same place file descriptor #1 (stdout) is currently pointing.”

Order is absolutely critical here. The shell processes redirections from left to right.

# Correct order: stdout goes to file, then stderr is sent to wherever stdout is going (the file).
$ ls -la fictional_dir real_file.txt > combined.txt 2>&1

# Wrong order: stderr is set to go to wherever stdout is going *at this moment* (the terminal). THEN stdout is redirected to the file.
$ ls -la fictional_dir real_file.txt 2>&1 > combined.txt

In the wrong example, the error messages will still spray across your terminal. You told stderr to go to the terminal’s stdout first, and then you changed where stdout itself goes. You broke the link. Always put the destination redirection (> file) before the duplication (2>&1).

The Black Hole of /dev/null

Sometimes, you don’t want the output or the errors. You just want to run a command and check its exit status. For this, we have the ultimate silencer: /dev/null.

# I don't care if it works or what it says, just run it and tell me if it succeeded (echo $?)
$ a_command_that_might_fail > /dev/null 2>&1

This is the standard “shut up” command. Redirect stdout to the null device, and then tell stderr to go to the same place. Beautifully quiet.

A Quick Note on Modern Syntax: &>

Some shells (like Bash) offer a shortcut because they know 2>&1 is a mouthful. You can use &>.

# These two commands are functionally identical in Bash
$ ls -la fictional_dir real_file.txt > combined.txt 2>&1
$ ls -la fictional_dir real_file.txt &> combined.txt

I’ll be honest with you: I still use > file 2>&1 out of habit and because it’s universally understood by all Bourne-style shells. &> feels a bit like a newcomer, but it’s perfectly valid and saves a few keystrokes. Your choice, but know what it means when you see it. The designers made a questionable choice by creating a new operator instead of just making the order of operations more intuitive, but here we are.