A lot of the power of the *nix shell is in redirection. The model is called “streams”, and we even have “pipes” for these “streams”. It’s not the best metaphor ever, but it’s good enough, I suppose. There are 3 streams associated with a process: the standard input (
stdin), standard output (
stdout) and standard error output (
stderr). As you might expect, you get user input on
stdin, output to
stderr, and send errors to
stdout : Redirecting Output
Let’s start with
stdout, the output stream, since that is the most common:
$ ls > /tmp/foo.txt $
This will run the “
ls” (list files) command, but instead of showing you the results, it will write to the file you specify (/tmp/foo.txt, in this example). If there is already a /tmp/foo.txt file, then it gets replaced.
$ ls >> /tmp/foo.txt $
>> instead of the single
>, we can append to the file instead of overwriting it.
If we want to see the output like we normally would, but log it to a file as well, we can use the “
$ ls | tee /tmp/foo.txt [ the usual ls output shown here ] $ ls | tee -a /tmp/foo.txt [ the usual ls output shown here ] $
The first command will write to /tmp/foo.txt; the second (with “
-a“) will append to /tmp/foo.txt.
We have used a different redirector here; “
|” (pipe) instead of “
>” and “
>>” . This is because we’re not funnelling the output to a different place (/tmp/foo.txt), but passing it to a program (
tee) which does some more funky redirection.
Another common use of the pipe (“
|“) is to go to the
less) utility. If a command would produce loads of output, faster than you can read it, then
more will pause after the screen is full, and prompt you with a “— more” prompt (hence the name). SPACE will show the next screen; RETURN will show the next line.
less is just like
more, but it can also go backwards (PgUp and PgDn):
$ ls | more file1.txt file2.txt file3.txt --- more (PRESS SPACE) file4.txt file5.txt file6.txt --- more (PRESS SPACE) file7.txt $
stderr : Redirecting Errors
Well-written programs will send their errors to a different “device” than they send their normal output to. Both
stderr are usually the same place (your terminal), but they can be treated separately:
$ ls foo.txt $ ls fo.txt ls: fo.txt: No such file or directory $ ls fo.txt > output.txt 2>errors.txt $ ls foo.txt output.txt errors.txt $ cat output.txt $ cat errors.txt ls: fo.txt: No such file or directory $
What happened there? Well, we asked for “
ls fo.txt“, but fo.txt doesn’t exist (foo.txt does). So we see an error from
ls. If we direct
stdout to “output.txt” and
stderr to “errors.txt”, then we can see the difference. What
ls actually did, was that it wrote *nothing* to
stdout and the error message was sent to
stderr has file descriptor #2, so we say “
2>” to direct stderr.) So when we “
cat output.txt“, we get nothing (there was no output), but when we “
cat errors.txt“, we see the error.
stdin: Redirecting Input
This is most commonly done by system utilities, but many shell scripts use the functionality.
The simple way is to use the “
$ mycommand < myfile.txt
This will take input from “myfile.txt” instead of from the keyboard.
The second way is probably more common. The
more example above had
more redirecting its input, via the pipe (“
|“). We can create entire pipelines this way:
$ find . -print | grep foo | more
This will attach the
stdout of the
find command to the
stdin of the
grep command, and attach the
grep to the
more. Got that?! So what the *nix kernel will do, is that it will start
more first, and then start
grep telling it that its
stdin. It will then start
find, and tell it that its
There’s actually more to it than that, but that’s got the basics of
stderr covered briefly.