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 /results
2
STDERR is also going directly to /results
the problem is this doesn't work as you would expect. consider the following:
file: /tmp/poem.txt
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
then
$ cat /tmp/results
grep: NOT_A_FILE: No such file or directory
lazy dog
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
>>
does.
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
The &
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.
For more information see - http://mywiki.wooledge.org/BashGuide/InputAndOutput#File_Redirection
program 1> /dev/null 2>/dev/null
. Some times though you do need to mix thestdout
andstderr
together to see what is really going on - like the output from a complex compile process being redirected to a file. In that case, I end up googling it