In regards to the bash shell I find the best way to remember is by understanding what is happening.
If all you want to do is remember how to get the command correct, you might try
program > /results 2> /results
That's nice and obvious whats going on and easy to remember. i.e.
1 STDOUT is going to
2 STDERR is also going directly to
the problem is this doesn't work as you would expect. consider the following:
the quick brown fox jumped over the lazy dog
and the run the command
grep "brown" /tmp/poem.txt NOT_A_FILE > /tmp/results 2> /tmp/results
$ cat /tmp/results
grep: NOT_A_FILE: No such file or directory
what happened here?
My understanding is bash setup the redirection pointing the STDERR directly to the file
/tmp/results and because of the nature of
> which does 2 things
- normally create a new file - in this case the opportunity has passed as bash has moved past this routine at the time the output is generated.
- insert straight into the beginning of the file. and not append like
So in this case STDERR, inserts directly into the beginning of
/tmp/results overriding the output of STDOUT.
Note: if you used
>> to append you could probably get away with this syntax.
However to fix the problem you need - not to redirect STDERR - to the file directly, but rather to merge STDERR's output into the STDOUT stream, so you don't get a collision.
Using the operator
2>&1 operator achieves this
grep "brown" poem.txt NOT_A_FILE > /tmp/results 2>&1
& enables bash to distinguish from a file named
1 and the
1 file descriptor.
To me the statement
2>&1 itself explains exactly what is happening - STDERR is being redirected at STDOUT itself - and only ends up in
/tmp/results because thats where STDOUT is pointed (almost as a side effect).
As opposed to what alot of guides claim, which is that
2>&1 sends STDERR to where ever STDOUT is pointed. If that were true - you would still have the overwriting problem.