I want to direct the output of a printf
in a bash
script to stderr
instead of stdout
.
I am not asking about redirecting either stderr
or stdout
from where ever they are currently routed. I just want to be able to send the output from a printf
to stderr
instead of to the default of stdout
.
I experimented a little and found that appending 1>&2
to the printf
, as shown in the example below, appears to do what I want. However, I have no experience using bash. So my primary question is if there is a "better" way to do this in bash
?
By "better" I mean is there another way to do this which is more commonly used, more conventional, or more idiomatic? How would a more experienced bash programmer do it?
#!/bin/bash
printf "{%s} This should go to stderr.\n" "$(date)" 1>&2
printf "[(%s)] This should go to stdout.\n" "$(date)"
I also have a secondary question. I am asking it not so much because I need to know, but more because I am just curious and would like to have a better understanding about what is happening.
It seems the above will only work when it runs inside a shell script. It does not appear to work when I try it from a command line.
Here is an example of what I mean.
irrational@VBx64:~$ printf "{%s} Sent to stderr.\n" "$(date)" 1>&2 2> errors.txt
{Sat Jun 9 14:08:46 EDT 2012} Sent to stderr.
irrational@VBx64:~$ ls -l errors.txt
-rw-rw-r-- 1 irrational irrational 0 Jun 9 14:39 errors.txt
I would expect the printf
command above to have no output because the output should go to stderr
, which in turn should go to a file. But this does not happen. Huh?
First, yes, 1>&2
is the right thing to do.
Second, the reason your 1>&2 2>errors.txt
example doesn't work is because of the details of exactly what redirection does.
1>&2
means "make filehandle 1 point to wherever filehandle 2 does currently" — i.e. stuff that would have been written to stdout now goes to stderr. 2>errors.txt
means "open a filehandle to errors.txt
and make filehandle 2 point to it" — i.e. stuff that would have been written to stderr now goes into errors.txt
. But filehandle 1 isn't affected at all, so stuff written to stdout still goes to stderr.
The correct thing to do is 2>errors.txt 1>&2
, which will make writes to both stderr and stdout go to errors.txt
, because the first operation will be "open errors.txt
and make stderr point to it", and the second operation will be "make stdout point to where stderr is pointing now".