What does 2>&1 mean?

April 17, 2020

If you have been shell scripting for a while, you may have seen 1>&2 or 2>&1 idioms. Ex:

SOME_COMMAND > /dev/null 2>&1

This article will explain what that strange-looking 2>&1 means.

TL;DR: 2>&1 means redirect the stderr (>2) to where stdout is being redirected to (&1).

Before we start, I want to go over a basic concept of file descriptors. There are 3 file descriptors in UNIX and each is associated with a number:

| Name | Short Name | File Descriptor Number| Description | | --------------:|:-------------:| ---------------------:| ---------------------: | Standard In | stdin | 0 | Keyboard Input | | Standard Out | stdout | 1 | Console Output | | Standard Error | stderr | 2 | Console Error Output |

We won't cover stdin in this article, but we will talk about stdout and stderr. Let's go!

stdout

When you execute a command, for example: ls. You will see the result of your command displayed on your screen. In this case, I see:

> ls
README.md      components       src       

Let's do one more:

> echo "hello"
hello

These are examples of stdout. They all have file descriptor value of 1. If you want to learn more about file descriptors, check out resources at the end of this post.

stdout redirection

You can redirect your stdout with >.

> echo "Hello stdout" > result.txt
> cat result.txt
Hello stdout

We no longer see "Hello stdout" after running echo. This is because instead of "Hello stdout" being displayed to console, it gets redirected to result.txt. The file result.txt contains our echo output: "Hello stdout".

Let's try one more:

> ls > result.txt
> cat result.txt
README.md
component
src 

This time you see the content of ls inside result.txt.

My point is, everything you see on your screen (that is not error) - every stdout - can be redirected with >.

By the way, > is actually a shorthand for 1>. If you do:

> echo "Hello redirection" 1> result.txt
> cat result.txt
Hello redirection

You get the same functionality using 1> as with >. Keep this in mind.

stderr

Sometimes we may encounter error running a command:

> cat filedoesntexist.txt
cat: filedoesntexist.txt: No such file or directory

> ls idontexist
ls: idontexist: No such file or directory

Let's compare running two different commands. Replace something_that_exists below with an actual file in your current directory.

> cat something_that_exists
> cat something_that_doesnt_exist

Although they each return some sort of output, your computer doesn't interpret these two outputs the same way. cat something_that_exists has file descriptor of 1 and cat something_that_doesnt_exist has file descriptor of 2.

stderr redirection

Let me show you how they're different. If we try to redirect a bad cat (😺 pun not intended):

> cat filedoesntexist > result.txt
cat: filedoesntexist: No such file or directory
> cat result.txt

You see cat: filedoesntexist: No such file or directory error displayed on your console and result.txt is empty. Our redirection redirects nothing.

This is because when we perform cat filedoesntexist, we get a stderr and not stdout. When we tried to redirect stdout to result.txt with > result.txt, there is no stdout to be redirected. To redirect stderr, we need to use stderr redirect, not stdout redirect. To redirect stderr, we use 2>.

> cat filedoesntexist 2> result.txt
> cat result.txt
cat: filedoesntexist: No such file or directory

This looks better. We no longer sees the error output when running cat filedoesntexist and our result.txt contains cat: filedoesntexist: No such file or directory error string. We have successfully redirected our bad cat 😸!

So we learned that there are at least 2 redirections: > and 2>. The former redirects normal outputs, the latter redirects error outputs.

To reinforce our knowledge, what do you think will happen if we do echo and use 2> redirection? Don't read further. Spend some time to think about this. When you're ready, read on.

. . . . . . . . . .

> echo "Hello Cat" 2> result.txt
Hello Cat
> cat result.txt

We see Hello Cat being echoed to our console and result.txt is blank, because we are redirecting stderr from our echo. Since our echo doesn't return any error, nothing gets redirected to result.txt.

stdout, stderr, and 2>&1

Let's do one last example.

> ls myDir > result.txt 2> result.txt

This will redirect stdout and stderr from running ls myDir to result.txt. This way, if myDir exists, it will redirect the output to result.txt and if myDir doesn't exist, it will redirect the error message to result.txt. User will not see any output whether the command works or not. It's a win-win.

This feels a bit too long, doesn't it? Luckily we can shorten it:

> ls myDir > result.txt 2>&1

Hey, look at that! Our 2>&1 idiom. It means redirect any stderr (2>) to the same place we are redirecting stdout (&1).

That's right! ls myDir > result.txt 2>&1 is the same as ls myDir > result.txt 2> result.txt. Think about this. Internalize it.

You can mix file descriptors, for example, what do you think this does?

> ls myDir 2> result.txt 1>&2

You might've guessed it now: 1>&2 means "redirect the stdout to where stderr is being redirected to".

So what do people use 2>&1 for? I have seen people running the command we see above (ex: Crontab quick reference (disable email)):

> CMD > /dev/null 2>&1

The script above redirects the output and error messages from whatever CMD you're running to /dev/null (if you're wondering what is /dev/null, it is a special file that discards everything written to it. I think of it like a black hole/ paper shredder).

This is a good place to stop.

I hope that makes sense so far. If not, I suggest either reread it or read some from resources below. Take your time understanding this, especially if it is new. It took me a while to understand it.

Thank you so much for reading! Appreciate it. Now go write some cool scripts with this!

Resources