Introduction to the Command Line

More about redirection

How do pipes work? They use three communication channels provided to every executing command.

stdin (standard input) by default is what we type on the keyboard. We can use "<" with a filename to make a program take input from a file.

stdout (standard output) by default is printed on your computer screen. We can use ">" with a filename to send that to a file, overwriting whatever is there, or we can use ">>" to append standard output to the end of the file.

stderr (standard error)  is an alternative kind of output. Programs use it to send error messages. This can be useful because you might want to see error messages on the terminal even if you redirect output to a file. Here's an example:

$ ls *.bak > listfile
ls: *.bak: No such file or directory

Here, we wanted a list of all files ending in .bak. But no such files exist in this directory. If ls sent its error message to standard output (which in this case has been directed to a file), we wouldn't know that there is a problem without looking at the content of listfile. But because ls sent its message to standard error, we see it. The error message starts with the name of the program (ls) followed by a colon and the actual message.

A pipe simply redirects the standard output of the first program to the standard input of the second:

$ ls *.bak | more

Sometimes, we want to direct the output of a command to a file, but we also want to see the output as the program runs. The tee command does just that:

$ ls -lR / | tee allMyFiles

provides a complete, detailed list of your file system, saved to allMyFiles. This takes some time to run; tee saves you from staring at a lifeless screen, wondering whether any thing's happening.

Each program can open a lot of files, and each has a number called a file descriptor that is meaningful only within that program. The first three numbers are always reserved for the file descriptors we just described.

 stdin  0
 stdout  1
 stderr  2

Redirecting stderr

When we redirect stdin as we did above, error messages still go to the screen.  For example
$ ls /nosuchplace > /dev/null
ls: /nosuchplace: No such file or directory
$

To redirect stderr we have to use the more general form of redirection, which uses the file numbers mentioned in the previous section, and looks like this.

$ ls /nosuchplace 2>/tmp/errors
$

This sends the error message sent to file number 2 (stderr) into the file /tmp/errors

Now we can introduce a more complex redirection, which redirects standard output and standard error to the same file:

$ ls *.bak > listfile 2>&1

The & in that command has nothing to do with putting a command in the background. The & here must directly follow the > character, and it sends file number 2 onto file number 1.

Or in the case of a pipe, put this before the pipe:

$ ls *.bak 2>&1 | more

Adding more descriptors

Sometimes it is convenient to keep other files open and add to them in dribs and drabs. You can do this with redirection and exec.

$ exec 3>/tmp/thirdfile
$ exec 4>/tmp/fourthfile
$ echo drib >&3
$ echo drab >&4
$ echo another drib >&3
$ echo another drab >&4
$ exec 3>&-
$ exec 4>&-

The first two lines open connections to two more file descriptors, 3 and 4.  We can then echo text onto them, redirect programs into them, etc. using >&3 or >&4.  Finally, we close them with the 3>&- and 4>&- syntax.