Categories
bash redirect shell unix

In the shell, what does ” 2>&1 ” mean?

2881

To combine stderr and stdout into the stdout stream, we append this to a command:

2>&1

e.g. to see the first few errors from compiling g++ main.cpp:

g++ main.cpp 2>&1 | head

What does 2>&1 mean, in detail?

7

  • 61

    @dbr I don’t think it’s just bash – I believe it’s a bourne shell thing; hence sh, bash, ksh, ash, dash, etc.

    – guns

    May 3, 2009 at 23:49

  • 8

    This is part of the redirection paragraph describing POSIX-compliant shells, or POSIX shell for short. ksh is a POSIX shell for example. See:pubs.opengroup.org/onlinepubs/009695399/utilities/…

    Apr 4, 2013 at 2:55


  • 15

    This construct also works on Windows.

    – Vadzim

    Oct 22, 2013 at 13:45

  • 7

    It’s generally better doing 2>&1 than 2>/dev/null 😉

    Dec 8, 2013 at 12:11


  • 15

    I thought I’d mention that |& is shorthand for 2>&1 | if you’re using zsh. I can’t speak to whether that applies to other bourne-like shells or if it’s a zsh only feature.

    – chrixian

    Dec 17, 2013 at 5:20


3199

File descriptor 1 is the standard output (stdout).
File descriptor 2 is the standard error (stderr).

At first, 2>1 may look like a good way to redirect stderr to stdout. However, it will actually be interpreted as “redirect stderr to a file named 1“.

& indicates that what follows and precedes is a file descriptor, and not a filename. Thus, we use 2>&1. Consider >& to be a redirect merger operator.

21

  • 370

    but then shouldn’t it rather be &2>&1?

    – dokaspar

    Sep 4, 2013 at 6:12

  • 405

    @Dominik: Nope, & is only interpreted to mean “file descriptor” in the context of redirections. Writing command &2>& is parsed as command & and 2>&1, i.e. “run command in the background, then run the command 2 and redirect its stdout into its stdout”.

    Jan 28, 2014 at 0:02

  • 61

    Why did they pick such arcane stuff as this? Just curious.

    May 17, 2014 at 4:00

  • 121

    But how would you redirect stderr to a file named ‘&1’?

    Nov 4, 2014 at 17:07

  • 175

    @Martin: 2>'&1'

    – user1247058

    Mar 14, 2016 at 10:46

853

To redirect stdout to file.txt:

echo test > file.txt

This is equivalent to:

echo test 1> file.txt

To redirect stderr to file.txt:

echo test 2> file.txt

So >& is the syntax to redirect a stream to another file descriptor:

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

To redirect stdout to stderr:

echo test 1>&2   # equivalently, echo test >&2

To redirect stderr to stdout:

echo test 2>&1

Thus, in 2>&1:

  • 2> redirects stderr to an (unspecified) file.
  • &1 redirects stderr to stdout.

5

  • 6

    does this make any sense to you, java ... 2&1 >> data.log, I saw one of my colleague did this?

    Jul 26, 2011 at 19:53


  • 7

    @Harry that looks like either a shell that isn’t bash, or a typo.. cmd 2>&1 >> somefile.log will append stdout/stderr to a file – it’s basically the same as above, with >> file to append

    – dbr

    Jul 27, 2011 at 0:38

  • 101

    @dbr cmd 2>&1 >>file does not redirect stderr to the file, but cmd >> file 2>&1 does. Order matters. In the first case, stderr is redirected to the stdout of the shell (possibly a tty if the command is entered interactively), and then stdout is directed to the file. In the second case, stdout is directed to the file, and then stderr is directed to the same place.

    Jul 19, 2013 at 13:15

  • 4

    I like the answer above, but it could be a touch clearer. “2>&1” redirects stderr to the target of stdout. So if you have something like “ls -l >> directoryContents 2>&1” The result will be a file named directoryContents will have the contents of the working directory appended to it. If there are any errors in execution: the error messages will also be appended to the directoryContents file, as they occur.

    – Max West

    Apr 17, 2015 at 17:36

  • 1

    Is 0(or 1,2)>&0(or 1,2) like an option to control the output? Is echo test >test.log 2>&1 same as echo test 2>&1 >test.log?

    – Cloud

    Jun 1, 2018 at 12:58


394

Some tricks about redirection

Some syntax particularity about this may have important behaviours. There is some little samples about redirections, STDERR, STDOUT, and arguments ordering.

1 – Overwriting or appending?

Symbol > means redirection.

  • > means send to as a whole completed file, overwriting target if exist (see noclobber bash feature at #3 later).
  • >> means send in addition to would append to target if exist.

In any case, the file would be created if they not exist.

2 – The shell command line is order dependent!!

For testing this, we need a simple command which will send something on both outputs:

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Expecting you don’t have a directory named /tnt, of course ;). Well, we have it!!

So, let’s see:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

The last command line dumps STDERR to the console, and it seem not to be the expected behaviour… But…

If you want to make some post filtering about standard output, error output or both:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Notice that the last command line in this paragraph is exactly same as in previous paragraph, where I wrote seem not to be the expected behaviour (so, this could even be an expected behaviour).

Well, there is a little tricks about redirections, for doing different operation on both outputs:

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Note: &9 descriptor would occur spontaneously because of ) 9>&2.

Addendum: nota! With the new version of (>4.0) there is a new feature and more sexy syntax for doing this kind of things:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

And finally for such a cascading output formatting:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Addendum: nota! Same new syntax, in both ways:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Where STDOUT go through a specific filter, STDERR to another and finally both outputs merged go through a third command filter.

2b – Using |& instead

Syntax command |& ... could be used as an alias for command 2>&1 | .... Same rules about command line order applies. More details at What is the meaning of operator |& in bash?

3 – A word about noclobber option and >| syntax

That’s about overwriting:

While set -o noclobber instruct bash to not overwrite any existing file, the >| syntax let you pass through this limitation:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

The file is overwritten each time, well now:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

Pass through with >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

Unsetting this option and/or inquiring if already set.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 – Last trick and more…

For redirecting both output from a given command, we see that a right syntax could be:

$ ls -ld /tmp /tnt >/dev/null 2>&1

for this special case, there is a shortcut syntax: &> … or >&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Nota: if 2>&1 exist, 1>&2 is a correct syntax too:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- Now, I will let you think about:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c- If you’re interested in more information

You could read the fine manual by hitting:

man -Len -Pless\ +/^REDIRECTION bash

in a console 😉

3