74

I don't quite understand how the computer reads this command.

cat file1 file2 1> file.txt 2>&1

If I understand, 2>&1 simply redirect Standard Error to Standard Output.

By that logic, the command reads to me as follows:

  1. concatenate files file1 and file2.

  2. send stdout from this operation to file.txt.

  3. send stderr to stdout.

  4. end?

I'm not sure what the computer's doing. By my logic, the command should be

cat file1 file2 2>&1 > file.txt

but this is not correct.

1
  • I find the man page utterly lacking and confusing here, and wonder how the people answering came up with their interpretations (correct though they may be). I can just about follow them myself, but to be honest I always just try it both ways as it seems somehow unintuitive, even after reading the answers below and going back to the man page.
    – m4r35n357
    Commented May 8 at 11:59

4 Answers 4

107

I find it easier to think of using assignments.

  • > is like =
  • & is like $

You start out with

1 = /dev/tty
2 = /dev/tty

then your first example, 1> file.txt 2>&1, does

1 = file.txt
2 = $1           # and currently $1 = file.txt

leaving you with

1 = file.txt
2 = file.txt

If you did it the other way, again you start with

1 = /dev/tty
2 = /dev/tty

then 2>&1 > file.txt does

2 = $1           # and currently $1 = /dev/tty
1 = file.txt

so the end result is

1 = file.txt
2 = /dev/tty

and you've only redirected stdout, not stderr.

5
  • 1
    i sort of get the analogy, but it's confusing - what does the $ stand for? Commented Jun 24, 2019 at 14:28
  • 3
    In an assignment like var=$othervar, $ introduces the variable name on the right hand side. In a redirection like 2>&1, & introduces the file descriptor number on the right hand side. I'm saying you can think of it like "file 2 equals file 1". (But there are two types of equals: < means "for reading" and > means "for writing".)
    – Mikel
    Commented Jun 25, 2019 at 15:48
  • 3
    For anyone who has ever found random files around named 1 or 2 you understand the difference between 2>1 and 2>&1 per @Mikel Also, I appreciate the mental translation, it works for me. 1>&2 becomes 1 = $2 which syntactically "sort of" means something in bash, RegEx, and probably Perl.
    – razzed
    Commented Sep 16, 2020 at 16:39
  • 2
    Another way to think about it is as memory pointers (C/C++) or references (Java): make stream 1 point to the desired output file, and then make stream 2 point to stream 1 (which is now the file).
    – ralfoide
    Commented Dec 21, 2021 at 22:45
  • Thank you! I never understood why the order matters but it makes sense when you think of ">" as a copy instead of a reference. Commented May 16, 2022 at 15:16
37

The order of redirection is important, and they should be read left to right.

For example: command 2>&1 >somefile means:

  1. Redirect the descriptor named 2 (bound to stderr) to the current destination of 1 (stdout) which at this point, reading left-ot-right is the terminal.
  2. Then change 1 (stdout) to go to somefile, which is a a file in disk

So in this case, stderr goes to the terminal, and stdout goes to a file, which isn't what you probably want.

On the other hand, command >somefile 2>&1 means:

  1. Redirect stdout to somefile
  2. Then redirect stderr to the same destination as stdout (somefile).

In this last case both stderr and stdout go to somefile, which is probably what you want.

2
  • in the last line , 2>&1 means: stderr goes to stdout right , where this "somefile" came here ? can you please throw some light... me confused a bit.
    – BdEngineer
    Commented Jun 8, 2020 at 12:57
  • With all the file descriptor operators one of the operand may be omitted. It is then equivalent to a 0 (stdin) or 1 (stdout), depending of the operator, or it may also be some ”special cases” where it isn’t 0 nor 1, nor any other file descriptor number. This is explained in the Bash manual at the very end of the REDIRECTION chapter. So to answer your question: >somefile is equivalent to 1>somefile. There are 10 redirection operators (in Bash, counting here-doc and here-string), so I can’t stress you enough to read the manual.
    – Stéphane
    Commented Apr 28 at 7:57
9
cat file1 file2 1> file.txt 2>&1

>& Actually means duplicate, it uses the dup system call to to map the file descriptor preceeding (2 in this example) onto an already opened file to the right (1 ie. stdout).

So, bash must first open the new stdout, before it can duplicated. It's like saying "stdout: re-direct to this file", followed by "stderr: redirect to whatever stdout is currently set to."

5
  • this is awesome! i been wondering about that &. could you enclose some references to that syntax, or - better yet - some good resources on the aforementioned dup system? Commented Jun 24, 2019 at 14:59
  • 1
    'man dup' documents the the system call.
    – X Tian
    Commented Jun 24, 2019 at 15:12
  • makes sense :) thanx Commented Jun 25, 2019 at 7:39
  • @X Tian , so here file1 & file2 goes to file.txt right ? so what is this "2>&1" ? i.e. stderro goes to stdout ? what to figure out what is duplicated here using ">&" ?
    – BdEngineer
    Commented Jun 8, 2020 at 13:00
  • The system call is actually called dup, read man dup. The thing being duplicated is the file descriptor, in C dup2(1, 2); will make fd2 (stderr) a copy of (duplicate) of fd1 (stdout)
    – X Tian
    Commented Jun 8, 2020 at 13:16
0

The command cat file1 file2 > file.txt 2>&1 sends both stdout and stderr of the cat command to file.txt. Now, this is only useful if somehow either file1 or file2 are not found, in which case error message saying 'file not found' will be saved to file.txt.

This is the same as cat file1 file2 &> file.txt.

Now the order of redirections matter. The following doesn't send stderr of cat command to file.txt but to the terminal.

$ cat file1 file2 2>&1 > file.txt 

This is because it is first copying the destination of stdout to stderr, but stdout at this stage is still pointing to the terminal. Then you redirected stdout to file.txt, so only stdout will be saved to file.txt. Error messages will still be printed to the screen and not saved to file.txt.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .