Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Can anyone help me understand this seemingly odd behavior of how the shell parses the redirects..?

$ cat > test.txt
Line 1
Line 2
$ ls -i dummy.txt dummy2.txt
ls: dummy.txt: No such file or directory
ls: dummy2.txt: No such file or directory
$ 
$ cat test.txt > dummy.txt > dummy2.txt
$ cat dummy2.txt
Line 1
Line 2
$ cat dummy.txt
$

Interesting! I would have expected the output from cat test.txt to be redirected into dummy.txt and then the shell would read dummy.txt as the input for dummy2.txt. But somehow the shell parses it differently...

So how does the content of test.txt be taken as the input for dummy2.txt, by bypassing dummy.txt altogether?


Note: Same result in bash and ksh..

share|improve this question
1  
If you run, in bash, cat test.txt > d1 > d2 > d3 > d4 > d5 then d1 through d4 will be empty, and the contents of test.txt will be in d5. Bash appears to perform the actual redirection only for the last file indicated. Curiously, ZSH (version 5 at least) will copy the contents of test.txt into all of the intermediary files as well. The BASH manpage does indicate that order of redirection is significant, and so it appears that the last indicated direction overrides the intermediaries. But, because they are there, bash creates those files before it notices where the actual content goes. –  SuperMagic Apr 8 '13 at 17:11
    
Wow.. That's good to know. @SuperMagic could you kindly post that as an answer.. Thanks! –  Kent Pawar Apr 8 '13 at 17:17
    
@SuperMagic zsh does that if MULTIOS is set only. –  Hauke Laging Apr 8 '13 at 17:45
add comment

2 Answers

up vote 4 down vote accepted

It's important to know that your shell is not redirecting the output, but the file descriptors. Every process on a POSIX-compatible operating system has 3 I/O streams: STDIN, STDOUT, and STDERR. The > redirection redirects the file descriptor for the STDOUT stream. So what the shell sees as it parses this line is:

  1. cat test.txt - Ok, I'll run the program cat and give it the argument test.txt
  2. > dummy.txt - Oh, now I'll take the STDOUT descriptor of the cat process and connect it to this file called "dummy.txt". I don't care if anything was there before, I'll create the file and truncate it to zero.
  3. > dummy2.txt - Oh, now I'll take the STDOUT descriptor of the cat process (that I previously connected to "dummy.txt") and connect it to a different new file. I can't do both things, because you're redirecting, not duping the file descriptors.

This is why this command:

find / 2>&1 >/dev/null

results in error output on STDOUT, and no regular (STDOUT) output, but this one:

find / >/dev/null 2>&1

results in no output at all. In the first case, we put STDERR on a copy (dup) of STDOUT, then put the old STDOUT in the trash. In the second, we first put STDOUT in the trash, then copy it (still pointed to /dev/null) and put STDERR there, too.

share|improve this answer
    
Duplicating file descriptors is quite different from duplicating output. –  Hauke Laging Apr 8 '13 at 17:46
add comment

From comment to answer, though some of this is speculation:

If you run, in bash,

cat test.txt > d1 > d2 > d3 > d4 > d5 

then d1 through d4 will be empty, and the contents of test.txt will be in d5. Bash appears to perform the actual redirection only for the last file indicated.

Curiously, zsh (version 5 at least) will copy the contents of test.txt into all of the intermediary files as well.

The bash manpage does indicate that order of redirection is significant, and so it appears that the last indicated direction overrides the intermediaries. But, because they are there, bash creates those files before it notices where the actual content goes.

The specific part of the man page reads as follows:

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.

This doesn't specifically cover the situation at hand, but does indicate that order does count. As such, seeing odd behavior when doing odd things (repeatedly redirecting stdout to different places) may have suprising results.

I'm sure someone will be along shortly to correct any wild (or mild) errors in this speculation:-)

share|improve this answer
2  
It's not curious, it's the multiple IOs feature enabled by default unless when emulating other shells. zsh performs an implicit tee when a fd is redirected several times. See the documentation for details. –  Stephane Chazelas Apr 8 '13 at 18:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.