There is basically no difference between reading data from a file and reading data from a terminal.[1] Likewise, if a program's output consists entirely of alphanumeric characters and punctuation, there is no difference between writing to a file, writing to a terminal, and writing to the input of another program (as in a pipe).
The standard I/O facility provides some simple defaults for managing input/output. There are three default I/O streams: standard input, standard output, and standard error. By convention, standard output (abbreviated stdout) consists of all "normal" output from your program, while standard error (stderr) consists of error messages. It is often a convenience to be able to handle error messages and standard output separately. If you don't do anything special, programs will read standard input from your keyboard, and they will send standard output and standard error to your terminal's display.
Standard input (stdin) normally comes from your keyboard. Many programs
ignore stdin; you name files directly on their command line
— for instance, the command cat file1 file2 never reads its
standard input; it reads the files directly. But without filenames on the
command line, Unix commands that need input will
usually read stdin. Standard input normally comes from your
keyboard, but the shell can redirect stdin from a file.
This is handy for Unix commands that can't open files directly — for instance,
mail (
Section 1.21). To mail a file to
joan, use <
filename
— to tell the shell to attach the file,
instead of your keyboard, to mail's standard
input:
% mail joan < myfile
The real virtue of standard I/O is that it allows you to redirect input or output away from your terminal to a file. As we said, Unix is file-based (Section 1.19). Because terminals and other I/O devices are treated as files, a program doesn't even need to know[2] if it is sending its output to a terminal or to a file. For example, if you want to run the command cat file1 file2, but you want to place the output in file3 rather than sending it to your terminal, give the command:
% cat file1 file2 > file3
This is called redirecting standard output to
file3. If you give this command and look at
file3 afterward, you will find the contents of
file1, followed by the contents of
file2 — exactly what you would have seen on your screen
if you omitted the > file3
modifier. (The
Z shell takes this further with multiple-file redirection.)
One of the best-known forms of
redirection in Unix is the pipe. The shell's vertical bar
(|
) operator makes a pipe. For example,
to send both file1 and file2 together
in a mail message for joan, type:
% cat file1 file2 | mail joan
The pipe says, "Connect the standard output of the process at the left
(cat
) to the standard input of the
process at the right (mail
)."
Section 36.15 has diagrams and more information about standard I/O and redirection. Table 43-1 shows the most common ways of redirecting standard I/O, for both the C shell and the Bourne shell, which also apply to derivatives like tcsh and bash.
Table 43-1. Common standard I/O redirections
Function |
csh |
sh |
---|---|---|
Send stdout to file |
|
|
Send stderr to file |
| |
Send stdout and stderr to file |
|
|
Take stdin from file |
|
|
Send stdout to end of file |
|
|
Send stderr to end of file |
| |
Send stdout and stderr to end of file |
|
|
Read stdin from keyboard until c (see Section 27.16) |
|
|
Pipe stdout to prog2 |
|
|
Pipe stdout and stderr to prog2 |
|
|
Be aware that:
While standard I/O is a basic feature of Unix, the syntax used to redirect standard I/O depends on the shell you are using. Bourne shell syntax and C shell syntax differ, particularly when you get into the less commonly used features. The Korn shell and bash are the same as the Bourne shell, but with a few twists of their own. The Z shell generally understands both syntaxes (and, in its usual manner, adds even more).
You can redirect standard input and standard output in the same command line. For example, to read from the file input and write to the file output, give the command:
% prog < input > output
The Bourne shell will let you go further and write stderr to a third file:
$ prog < input > output 2> errors
The C shell doesn't give you an easy way to redirect standard output without redirecting standard error. A simple trick will help you do this. To put standard output and standard error in different files, give a command like:
% ( prog > output ) >& errors
We'll discuss commands like this in Section 43.3 and Section 43.5.
Many implementations of both shells don't care what order the
redirections appear in, or even where they appear on the command line.
For example, SunOS lets you type <
input
>
output
prog
. However, clarity is a virtue
that computer users have never appreciated enough. It will be easiest to
understand what you are doing if you type the command name first — then
redirect standard input, followed by standard output, followed by
standard error.
There are some more complex forms of standard I/O redirection, particularly for the Bourne shell (Section 36.16).
Of course, programs aren't restricted to standard I/O. They can open other files, define their own special-purpose pipes, and write directly to the terminal. But standard I/O is the glue that allows you to make big programs out of smaller ones, and it is therefore a crucial part of the operating system. Most Unix utilities read their data from standard input and write their output to standard output, allowing you to combine them easily. A program that creates its own special-purpose pipe may be very useful, but it cannot be used in combination with standard utilities.
Many Unix systems, and utilities such as gawk ( Section 20.11), support special filenames like /dev/stdin, /dev/stdout, and /dev/stderr.[3] You can use these just as you'd use other files. For instance, to have any ordinary command read from the file afile, then standard input (from the keyboard, for example), then the file bfile:
%somecmd
afile /dev/stdin bfile
In the same way, a process can write to its standard output through /dev/stdout and the standard error via /dev/stderr.
Because reading from standard input and standard output is so common, there is
a more general convention for redirecting to these two devices: using -
where a program expects a filename. If the
program was expecting the name of an input file, it will read from standard
input instead. If it was expecting an output file, it will write to standard
output. A very common place this is seen is in the unpacking of
tar
gzipped archives:
$ gzip -dc filename
.tar.gz | tar -xvf -
Here, the -c
flag tells gzip to stream the uncompressed file to standard
output, which is then piped to tar. The
-f
flag of tar is used to specify the
source tar file, which, because of the -
, is
standard input.
[1] If a program's input consists entirely of alphanumeric characters and punctuation (i.e., ASCII data or international (non-English) characters).
[2] But it can find out.
[3] On Linux, at least, those are symbolic links (Section 10.4) to /proc/self/fd/0, /proc/self/fd/1, and /proc/self/fd/2, respectively.