How Do I Use Shell Redirection?

>This article was originally written by Tillman Hodgson. The most current version of it (and the copyright notice) can be found on his site.

Note that everything in this section applies to the bash shell; other shells may not have as many or the even the same features. Even though standard input/output redirection is a basic feature of any Unix derivative, the syntax does depend on the shell that you're using.

There are all sorts of redirection symbols that you can use. Here's a quick table of the common ones:

The problem with cats ...

Take a simple redirection example such as this:

cat file1 | tr -d '\015' > file2

You've wasted a process on cat, since you could accomplish the same thing (and have it execute faster!) by doing this:

tr -d '\015' < file1 > file2

Sending stderr through a pipe

Sending only stderr down a pipe, while having stdout still go to the screen, is an interesting trick. It can be done by passing the stdout and stderr file descriptors to temporary file descriptors, and basically playing a game of 3 card monte with the values:

(binary 3>&1 1>&2 2>&3 3>&-) | mail me@somewhere.org &

This runs the program called "binary" and mails the errors to me@somewhere.org, while leaving the regular stdout output going to the screen. If you can follow this, you didn't need to read this document ;-)

Splitting output

If you run your output through a program called tee (usually found at /usr/bin/tee), you can split your stdout stream. This can be very useful if you want to save the output of a command to a file, but you also want to view it on the screen. For example:

binary | tee results.file | lpr

takes the results of the command named "binary" and saves the stdout to ta file called "results.file" as well sending the stdout to be printed.

Why is it > somefile 2>&1 rather than 2>&1 > somefile?

The command cat file1 2>&1 >file2 results in an error message, yet cat file1 > file2 2>&1 works. This seems rather odd at first.

Whats happening is that the shell is reading the commands from left to right. The reason the first command fails is that bash sees the 2>&1 first. It thinks, "Ok, I'll send the stderr to the same place and stdout", which has no effect because they're both already going to the terminal. Then the > redirects stdout to file2, but stderr is still going to the terminal. In the second example, if you read it strictly from left to right, you'll see that it makes more sense.