Why is 1>a.txt 2>&1 different from 1>a.txt 2>a.txt ? (Example shown)
With 1>a.txt 2>&1
, file descriptor #1 is duplicated to #2. They both reference the same "open file", and they both share the current position and r/w mode. (There's actually no difference at all between using 2>&1 and 2<&1.)
With 1>a.txt 2>a.txt
, both file descriptors are opened independently and have separate cursor positions. (The file gets truncated twice too.) If you write "Hello" to fd #1, its position is advanced to byte 5, but fd #2 remains at byte 0. Printing to fd #2 will just overwrite the data starting from 0.
This is easy to see if the second write is shorter:
$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>a.txt
$ cat a.txt
123defg
Note that Perl has internal buffering, so in this example an explicit flush() is necessary to ensure that fd #1 data is written before fd #2 data. Otherwise, the streams would be flushed in unpredictable order on exit.
For comparison, if the file descriptors are shared, the writes just follow each other:
$ perl -e 'STDOUT->print("abcdefg\n"); STDOUT->flush; STDERR->print("123");' >a.txt 2>&1
$ cat a.txt
abcdefg
123