sending output to /dev/stderr vs. >&2

The special device /dev/stderr is system-specific, while the file descriptor 2 (not the special device /proc/self/fd/2) is portable. If you want to write non-portable code, those special devices are a good place to start.

There are a few systems with /dev/stderr: Linux, of course, and OSX. But OSX has no /proc filesystem, and its /dev/stderr is a link to /dev/fd/2.

Further reading:

  • Portability of “> /dev/stdout”
  • What method should I use to write error messages to 'stderr' using 'printf' in a bash script?
  • patches/awk-dev-stderr (autoconf-patches)
  • Redirect stderr and stdout in a Bash script
  • Chapter 20. I/O Redirection (Advanced Bash-Scripting Guide)

In bash, and other shells, the way to redirect something to standard error is to use >&2. Bash opens /dev/stderr as the file descriptor 2. File descriptors are referenced by &N where N is the number of the descriptor. So, echo error >&2 will print error to standard error, to /dev/stderr.

It will also open /dev/stdout as file descriptor 1. This means you can do echo output >&1. However, since everything is printed to standard output anyway by default, that is the same as echo output by itself.

Now, 2> is different. Here, you are redirecting the error output of a command somewhere else. So, 2>file means "redirect anything printed to file descriptor 2 (standard error) to file".


You're right, >&2 is more direct and perfectly "idiomatic". They should be equivalent, so there's no particular reason to use >/dev/stderr. Except that, if someone reading doesn't know what these do, one of them is probably easier to find out than the other :-). But in general I'd suggest you use >&2.

/dev/stderr could be useful when programs will write errors to a specified filename, but don't support stderr. Clearly this is a bit contrived; /dev/stdout is much more useful. (I recently found the mysql_safe wrapper script won't write errors to the console; unfortunately it also wants to change the permissions on the error log file, so using /dev/stderr causes a few superfluous warnings).