A Brief Intro
When i take a look at bash’s documentation about shell redirection , i found out that this two examples are different. This one:
ls > dirlist 2>&1
and this one:
ls 2>&1 > dirlist
So let’s try understanding why it is different.
What 2>&1 means?
From this hacker news
comment
, it looks like the
expression 2>&1 is like calling system call dup2(2, 1). If we take a look
at the man page (man dup2), here is one of the description:
In other words, the file descriptor
newfdis adjusted so that it now refers to the same open file description asoldfd.
From that man page description, when we use expression 2>&1, we are telling
the shell to use standard output’s file descriptor for standard error’s file
descriptor, which means that the file descriptor used for standard output and
standard error is the same.
For those who are new to the term standard output and standard error, you
can take a look at this standard output
definition
and standard error
definition
. To make things
simpler, standard output is the destination for the non-error output and
standard error is the destination for the error output.
In
POSIX
compliant system, the representation for standard output is 1 and standard error is 2 and these number also representing the file descriptor number.
That’s why when we are using expression 2>&1, the number 2 in those
expression means standard error and the number 1 means standard output.
The Order Matters
Let’s try analyzing the possible scenario between the previous example command.
Before we dive in, if you didn’t know about shell redirection, you should read the bash documentation above or this blog post about shell redirection .
If you are curious about file descriptor, you can take a look at this chapter from computer science from the bottom up .
Analyzing First Example
Let’s take a look at the first command:
ls > dirlist 2>&1
The expression > dirlist, or we can also write >dirlist, means that we are
changing the file descriptor for standard output from the default file
descriptor 1 to dirlist’s file descriptor.
The expression 2>&1, or we can also write 2>& 1 (Notice that the number 2
and the symbol is not separated? That is one syntax), means that we are
changing the standard error file descriptor from the default file descriptor
2 to standard output’s file descriptor.
Because we already changed the standard output’s file descriptor previously
with expression > dirlist, that means the standard error’s file descriptor
is also dirlist’s file descriptor. In this first command, the file
descriptor for standard output and standard error is the same, which is
dirlist file descriptor.
Analyzing Second Example
Let’s take a look at the second command:
ls 2>&1 > dirlist
The expression 2>&1 means that we are changing the standard error file
descriptor from the default file descriptor 2 to standard output’s file
descriptor. Keep in mind that we have not changed the standard output’s file
descriptor yet, and that means the standard output still have default file
descriptor, which is file descriptor 1.
The expression > dirlist means that we are changing the file descriptor for
standard output from the default file descriptor 1 to dirlist’s file
descriptor. Keep in mind that redirection attached to the file descriptor, not
to specific standard stream like standard output or standard error. So
when the standard output’s file descriptor changed later, like in the second
command, it does not effect the standard error’s file descriptor.
With that in mind, in this second command, the file descriptor for standard output and standard error is not the same. The file descriptor for
standard output is dirlist’s file descriptor, and the file descriptor for
standard error is 1 (the former standard output’s file descriptor).
We can make the standard error’s file descriptor the same as standard output’s file descriptor by using the redirection again, like this:
ls 2>&1 > dirlist 2>&1
but keep in mind that using redirection like that on different POSIX shell may
result in undefined behavior. I noticed running the command above in zsh
and bash give different result.
Conclusion
The shell redirection order is important as it might produce unexpected result when we use incorrect order.
Alright, that’s it. See you next time!