home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

Unix Power ToolsUnix Power ToolsSearch this book

36.16. n>&m: Swap Standard Output and Standard Error

By default, a command's standard error goes to your terminal. The standard output goes to the terminal or is redirected somewhere (to a file, down a pipe, into backquotes).

Sometimes you want the opposite. For instance, you may need to send a command's standard output to the screen and grab the error messages (standard error) with backquotes. Or you might want to send a command's standard output to a file and the standard error down a pipe to an error-processing command. Here's how to do that in the Bourne shell. (The C shell can't do this, although tcsh can.)

File descriptors 0, 1, and 2 are, respectively, the standard input, standard output, and standard error (Section 36.15 explains). Without redirection, they're all associated with the terminal file /dev/tty (Section 36.15). It's easy to redirect any descriptor to any file -- if you know the filename. For instance, to redirect file descriptor 2 to errfile, type:

$ command 2>errfile

You know that a pipe and backquotes also redirect the standard output:

$ command | ...
$ var=`command`

But there's no filename associated with the pipe or backquotes, so you can't use the 2> redirection. You need to rearrange the file descriptors without knowing the file (or whatever) that they're associated with. Here's how. You may find it useful to run this short Perl script, which simply prints "stdout" to standard output, and "stderr" to standard error:


print STDOUT "stdout\n";
print STDERR "stderr\n";

Let's start slowly. We will combine both standard output and standard error, sending them both as output, to be used as the input to a pipe or as the output of backquotes. The Bourne shell operator n>&m rearranges the files and file descriptors. It says, "Make file descriptor n point to the same file as file descriptor m." Let's use that operator on the previous example. We'll send standard error to the same place standard output is going:

$ command 2>&1 | ...
$ var=`command 2>&1`

In both those examples, 2>&1 means "send standard error (file descriptor 2) to the same place standard output (file descriptor 1) is going." Simple, eh?

You can use more than one n>&m operator. The shell reads them left-to-right before it executes the command.

"Oh!" you might say. "To swap standard output and standard error -- make stderr go down a pipe and stdout go to the screen -- I could do this!"

$ command 2>&1 1>&2 | ...     wrong...

Sorry, Charlie. When the shell sees 2>&1 1>&2, the shell first does 2>&1. You've seen that before -- it makes file descriptor 2 (stderr) go the same place as file descriptor 1 (stdout). Then the shell does 1>&2. It makes stdout (1) go the same place as stderr (2)... but stderr is already going the same place as stdout, down the pipe.

This is one place the other file descriptors, 3 through 9 (and higher in bash), come in handy. They normally aren't used. You can use one of them as a "holding place," to remember where another file descriptor "pointed." For example, one way to read the operator 3>&2 is "make 3 point the same place as 2." After you use 3>&2 to grab the location of 2, you can make 2 point somewhere else. Then make 1 point where 2 used to (where 3 points now).

We'll take that step-by-step below. The command line you want is one of these:

$ command3>&2 2>&1 1>&3 | ...
$ var=`command 3>&2 2>&1 1>&3`

How does it work? Figure 36-3 through Figure 36-6 break the second command line (with the backquotes) into the same steps the shell follows as it rearranges the file descriptors. You can try these on your terminal, if you'd like. Each figure adds another n>&m operator and shows the location of each file descriptor after that operator.

Figure 36-3

Figure 36-3. File descriptors before redirection

Figure 36-4

Figure 36-4. File descriptors after 3>&2 redirection

The figures use a grep command reading two files. afone is readable, and grep finds one matching line in it; the line is written to the standard output. bfoen is misspelled and so is not readable; grep writes an error message to the standard error. In each figure, you'll see the terminal output (if any) just after the variable-setting command with the backquotes. The text grabbed by the backquotes goes into the shell variable; the echo command shows that text.

Figure 36-5

Figure 36-5. File descriptors after 3>&2 2>&1 redirection

By Figure 36-6 the redirection is correct. Standard output goes to the screen, and standard error is captured by the backquotes.

Figure 36-6

Figure 36-6. File descriptors after 3>&2 2>&1 1>&3 redirection

Open files are automatically closed when a process exits, but it's safer to close the files yourself as soon as you're done with them. That way, if you forget and use the same descriptor later for something else (for instance, use F.D. 3 to redirect some other command, or a subprocess uses F.D. 3), you won't run into conflicts. Use m<&- to close input file descriptor m and m>&- to close output file descriptor m. If you need to, you can close standard input with <&- and standard output with >&-.

-- JP

Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.