If you have been shell scripting for a while, you may have seen
2>&1 idioms. Ex:
SOME_COMMAND > /dev/null 2>&1
This article will explain what that strange-looking
2>&1 means redirect the stderr (
>2) to where stdout is being redirected to (
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|
||2||Console Error Output|
We won't cover
stdin in this article, but we will talk about
stderr. Let's go!
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.
You can redirect your
> 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
Let's try one more:
> ls > result.txt > cat result.txt README.md component src
This time you see the content of
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.
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.
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
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
> 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
cat: filedoesntexist: No such file or directory error string. We have successfully redirected our bad
So we learned that there are at least 2 redirections:
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
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
Let's do one last example.
> ls myDir > result.txt 2> result.txt
This will redirect
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 (
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!