What method should I use to write error messages to 'stderr' using 'printf' in a bash script?
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".
That seems reasonable to me. You don't need the
1
, though - it will work as is, but it's implied:printf "{%s} This should go to stderr.\n" "$(date)" >&2
You have an order-of-operations problem:
$ printf "{%s} Sent to stderr.\n" "$(date)" 2> errors.txt 1>&2$ ls -l errors.txt -rw-r--r-- 1 carl staff 47 Jun 9 11:51 errors.txt$ cat errors.txt {Sat Jun 9 11:51:48 PDT 2012} Sent to stderr.
The typical idioms are:
echo foo >&2 # you don't need to specify file descriptor 1echo foo > /dev/stderr # more explicit, but wordier and less portable