I/O Redirection: Swap stdout And stderr

Basic Pipe Usage

Programs which write to standard output are good members of a pipeline:

Couting directory entries below /etc
$ find /etc | wc -l
find: `/etc/cron.daily': Permission denied
find: `/etc/sudoers.d': Permission denied
find: `/etc/cron.weekly': Permission denied
... 18 - 3 = 15 errors on stderr omitted ...
1558

Basic Pipe Usage: What The Shell Does

  • Allocates pipe

  • Duplicates find ‘s stdout to go into the pipe’s write-end

  • Duplicates wc ‘s stdin to come from the pipe’s read-end

../../../../../../_images/io-redir-swap-stderr-and-stdout-orig.svg

And How Do I Count Lines On stderr?

Obviously: standard output and standard error need to be swapped!

$ find /etc 3>&1 1>&2 2>&3 | wc -l
... stderr omitted ...
18

What?

  1. A>&B: make file descriptor A refer to the object that is pointed to by file descriptor B

  2. Redirections are applied/evaluated left to right

3>&1

Create file descriptor 3 to point to stdout (which goes into the pipe)

../../../../../../_images/io-redir-swap-stderr-and-stdout-step1.svg
1>&2

Redirect stdout to go where stderr currently points to (i.e. the terminal)

../../../../../../_images/io-redir-swap-stderr-and-stdout-step2.svg
2>&3

Redirect stderr to where file descriptor 3 currently points to (the pipe)

../../../../../../_images/io-redir-swap-stderr-and-stdout-step3.svg

More Tricks

The original find output (the entries that it finds) still go on the terminal. Silence that by discarding output on 1:

$ find /etc 3>&1 1>&2 2>&3 1>/dev/null | wc -l
18

Being overly correct, we can close file descriptor 3 after all redirections have been applied:

$ find /etc 3>&1 1>&2 2>&3 1>/dev/null 3>- | wc -l
18