4

Can somebody please clarify differences? Is some of those considered as best practice? If I remember correct I somehow on SO read that this 1>/dev/null should precede this: 2>&1

ls -al /doesNotExists 2>&1 1>/dev/null
ls -al /doesNotExists 1>/dev/null 2>&1

ls -al /doesNotExists 1>&2 2>/dev/null
ls -al /doesNotExists 2>/dev/null 1>&2

ls -la /doesNotExists 2<&1 1>/dev/null
ls -la /doesNotExists 2<&1 2>/dev/null

ls -la /doesNotExists 1<&2 1>/dev/null
ls -la /doesNotExists 1<&2 2>/dev/null

ls -la /doesNotExists 1>/dev/null 2<&1
ls -la /doesNotExists 2>/dev/null 2<&1

ls -la /doesNotExists 1>/dev/null 1<&2
ls -la /doesNotExists 2>/dev/null 1<&2
2

1 Answer 1

8

shell standard streams redirection order

The order matters as the outcome is different. Take your first example:

ls -al /doesNotExists 2>&1 1>/dev/null

This directs only standard output to nul, because the standard error was duplicated to standard output before standard output was redirected to dirlist.

ls -al /doesNotExists 1>/dev/null 2>&1

This directs both standard output and standard error to nul.


Bash Reference Manual: Redirections

Note that the order of redirections is significant. For example, the command

ls > dirlist 2>&1

directs both standard output (file descriptor 1) and standard error (file descriptor 2) to the file dirlist, while the command

ls 2>&1 > dirlist

directs only the standard output to file dirlist, because the standard error was made a copy of the standard output before the standard output was redirected to dirlist.

Source Bash Reference Manual: Redirections


Tutorial

There is a nice illustrated tutorial at Illustrated Redirection Tutorial which makes this easier to understand:

Order Of Redirection, i.e., "> file 2>&1" vs. "2>&1 >file"

While it doesn't matter where the redirections appears on the command line, their order does matter. They are setup from left to right.

2>&1 >file

A common error, is to do command 2>&1 > file to redirect both stderr and stdout to file. Let's see what's going on. First we type the command in our typical terminal, the descriptors look like this:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

Then our shell, Bash sees 2>&1 so it duplicates 1, and the file descriptor look like this:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

That's right, nothing has changed, 2 was already pointing to the same place as 1. Now Bash sees > file and thus changes stdout:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

And that's not what we want.

>file 2>&1

Now let's look at the correct command >file 2>&1. We start as in the previous example, and Bash sees > file:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

Then it sees our duplication 2>&1:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| file                  |
                  ---       +-----------------------+

And voila, both 1 and 2 are redirected to file.

5
  • Thank you, nice info graphic. Just two clarifications: 1. ls > /dev/null is it the same as ls 1> /dev/null 2. When are < used? I have tried ls -l >file &1<2 and it is not the same as ls >file 2>&1. Is cat file equivalent to cat <file are there any examples where it is not equivalent? thank you Feb 27, 2015 at 22:15
  • @WakanTanka 1/ yes (1 just means std output). 2/ < is used to redirect input (cat file is the same as cat < file)
    – DavidPostill
    Feb 27, 2015 at 22:33
  • When it is useful to redirect input, it can open it as I've shown, why redirect? Feb 27, 2015 at 22:44
  • Just to clarify the answer in the comment: cat <file is the same as cat file because cat reads from stdin when it gets no arguments. ls file is not the same as ls <file, as the later expects to find a list of files inside file, and the former just list one single file, file. Apr 21, 2015 at 18:42
  • This explanation is very nice. Thanks for the diagram. Apr 29, 2016 at 6:17

You must log in to answer this question.

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