Shell, explained

stdin, stdout and stderr: what are streams 0, 1 and 2?

ls notes.txt nope.txt > out.txt 2> err.txt

Every program starts with three open streams, each known by a number called a file descriptor: 0 is standard input (what it reads), 1 is standard output (its results) and 2 is standard error (its complaints). All three begin connected to your terminal. Redirections such as > and 2> reconnect one of them to a file, and the program never knows the difference.

Three streams, and where each one goes

notes.txt exists and nope.txt does not, so ls prints one line on each output stream. Pick a command and watch the streams move.

Nothing is redirected: all three streams are connected to the terminal, so results and errors look the same on screen.

lsITS OPEN STREAMS
Tap a command to see where each stream goes

Part by part

ls notes.txt nope.txt
Prints the name it finds on stream 1 and an error for the missing one on stream 2.
>
Short for 1>: connects stream 1 (stdout) to a file.
out.txt
Receives the normal output.
2>
Connects stream 2 (stderr) to a file. The 2 must touch the >.
err.txt
Receives the error messages.

Common mistakes

Printing your own errors on stdout

In a script, echo "file missing" goes to stream 1 and ends up in pipes and output files. Send messages for the human to stream 2: echo "file missing" >&2.

A space in 2 >

ls 2 > out.txt is not a redirection of errors: 2 becomes an argument, and ls goes looking for a file named 2.

Try it

$ ls /dev/fd

The streams ls itself has open: 0, 1, 2 and the folder it is reading.

$ echo oops >&2

Write to stream 2. It looks the same on screen, but a pipe will not carry it.

$ exec 3> log.txt; echo hello >&3; exec 3>&-

Open your own stream 3, write to it, close it.

Questions

What is a file descriptor?

A small number a program uses to refer to something it has open: a file, a pipe, a terminal, a network connection. The system keeps a table per program; 0, 1 and 2 are simply its first three rows, filled in before the program starts.

Why are errors on a separate stream?

So that a pipe or an output file receives only the results. In ls | wc -l the count is not thrown off by an error message, and you still see the message on screen.

Are there more than three?

Yes. Every file a program opens gets the next free number: 3, 4, 5 and so on. The shell can open them too, as in exec 3> log.txt.

Where does stdin come from when nothing is redirected?

From your keyboard. Run sort with no arguments, type a few lines and press Ctrl-D: sort was reading stream 0 the whole time.

Terminaster

Stop looking up the same command twice.

Ask about any command you run into and see what it actually does. Terminaster then brings it back just before you would forget it, until you can type it without searching.

Terminaster's tutor answering “What does chmod 754 mean?” by taking the command apart: chmod, then 7 for you, 5 for your group, 4 for everyone else, and the file name