man bash
says this on redirection:
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 command
ls 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 to dirlist.
I really do not understand the part:
the standard error was duplicated from the standard output before the standard output was redirected to dirlist.
From my perspective >
just means redirection, like ls > dirlist
redirects output of ls
into file dirlist
.
So 2>&1
should redirect stderr to stdout, which then should get redirected to dirlist
(> dirlist
). However, apparently only stdout gets redirected to dirlist
then.
What's the business with this "stream A duplicated from stream B"?
CodePudding user response:
Shell redirections literally just invoke the syscall dup2()
. Quoting from https://man7.org/linux/man-pages/man2/dup.2.html --
int dup2(int oldfd, int newfd);
The dup() system call allocates a new file descriptor that refers to the same open file description as the descriptor oldfd.
This isn't actually doing anything like "redirecting streams" -- instead, it's changing the table of open files to make a file handle at one position in the table be pointed to from another location in the table.
So, let's look at your first example, ls > dirlist 2>&1
- The file
dirlist
is opened withopen(2)
. dup2()
is used to copy the file handle created byopen()
to FD 1 (the default for>
), and the dynamically-created handle is closed.dup2()
is used to copy FD 1 to FD 2.
...net result: both FD 1 and FD 2 point to dirlist
.
Now, let's look at your next example, ls 2>&1 >dirlist
dup2()
is used to copy whatever was previously opened at FD 1 to FD 2open()
is used to open the filedirlist
dup2()
is used to copy the handle on dirlist to FD 1, and the dynamically-created handle is closed.
...net result: FD 2 now points to the prior value of FD 1, and FD 1 now points to dirlist
.
CodePudding user response:
Your manual is a bit different from the one available at the GNU website, but take a look at Duplicating File Descriptors:
The redirection operator [n]<&word is used to duplicate input file descriptors. If word expands to one or more digits, the file descriptor denoted by n is made to be a copy of that file descriptor...The operator [n]>&word is used similarly to duplicate output file descriptors.
So when you write 2>&1
you're saying you want file descriptor 2 to become a copy of file descriptor 1. It doesn't literally get connected to file descriptor 1, it just points at the same place. Since it's just a copy, changes to file descriptor 1 don't automatically apply back to file descriptor 2. That's why the order matters.