How to understand the ordering of output redirection? [duplicate]
Solution 1:
The order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist, while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard error was duplicated from the standard output (typically still pointing to a terminal window) before the standard output was redirected to dirlist.
At first this may feel counter-intuitive, but after thinking about it, we can understand it.
You find this explanation in man bash
, in the chapter about redirection,
REDIRECTION
Before a command is executed, its input and output may be redirected using a special notation interpreted by the shell. Redirection allows commands file handles to be duplicated, opened, closed, made to refer to different files, and can change the files the command reads from and writes to. Redirection may also be used to modify file handles in the current shell execution environment. The following redirection operators may precede or appear anywhere within a simple command or may follow a command. Redirections are processed in the order they appear, from left to right.
Each redirection that may be preceded by a file descriptor number may instead be preceded by a word of the form
{varname}
. In this case, for each redirection operator except>&-
and<&-
, the shell will allocate a file descriptor greater than or equal to 10 and assign it tovarname
. If>&-
or<&-
is preceded by{varname}
, the value ofvarname
defines the file descriptor to close.In the following descriptions, if the file descriptor number is omitted, and the first character of the redirection operator is
<
, the redirection refers to the standard input (file descriptor 0). If the first character of the redirection operator is>
, the redirection refers to the standard output (file descriptor 1).The word following the redirection operator in the following descriptions, unless otherwise noted, is subjected to brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, quote removal, pathname expansion, and word splitting. If it expands to more than one word, bash reports an error.
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file
dirlist
, while the commandls 2>&1 > dirlist
directs only the standard output to file
dirlist
, because the standard error was duplicated from the standard output before the standard output was redirected todirlist
.
Edit: The following command lines might explain what happens
Prepare
sudodus@xenial32:~$ touch qwerty;rm asdf
rm: cannot remove 'asdf': No such file or directory
Run the list command for one existing file and one non-existing file
sudodus@xenial32:~$ ls qwerty asdf
ls: cannot access 'asdf': No such file or directory
qwerty
Redirect the error output before redirecting the standard output. Only the standard output is redirected to the output file.
sudodus@xenial32:~$ ls qwerty asdf 2>&1 > output-file ;echo '---';cat output-file
ls: cannot access 'asdf': No such file or directory
---
qwerty
Redirect the error output after redirecting the standard output. Both the error output and the standard output are redirected to the output file.
sudodus@xenial32:~$ ls qwerty asdf > output-file 2>&1 ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty
The token &>
can be used to redirect both the standard error and standard output. It can be used in bash
, but may not be available in other shells.
sudodus@xenial32:~$ ls qwerty asdf &> output-file ;echo '---';cat output-file
---
ls: cannot access 'asdf': No such file or directory
qwerty
sudodus@xenial32:~$
Solution 2:
-
2>x
means that filenamex
will receive the data written to descriptor2
(also known as stderr, standard error) - ... but when
x
is specified as&1
it doesn't mean "always follow1
"; it means "copy the current properties of1
(and then leave it alone)". - Redirections are applied in the same order as entered on the command line, but before the actual execution happens.
This is why 2>&1 1>whatever
outputs stderr to terminal.
This is why find / -name mylostfile.txt 3>&1 1>&2 2>&3 | grep -v 'Permission denied'
exchanges stderr and stderr, so that you can filter some common stderr lines out, but still see all the stdout. (Descriptor 3 here is unused by programs).
Solution 3:
The shell encounters and sets in the order it sees thing. In the first case:
ls here.txt not-here.txt 1>out 2>&1
The output is redirected, then standard error is sent to the same place.
In the second case,
ls here.txt not-here.txt 2>&1 1>out
Standardout out is still set to the terminal, so standard error is sent to the terminal THEN standard out is changed. The shell has already set standard error.