Three doors every program has
Every Unix process is born with three open file descriptors: stdin (0), stdout (1), stderr (2). They are how the kernel and the shell talk to your program. The shell's pipes and redirections are nothing more than wiring up these three doors to different things.
Default wiring
- stdin (0) — your keyboard.
- stdout (1) — your terminal screen.
- stderr (2) — also your terminal screen, but a separate stream so errors don't mix into a pipe.
Why two output streams?
Imagine find / -name foo 2>/dev/null | grep bar. The errors ("Permission denied") go to stderr, which you silence with 2>/dev/null. The actual matches go through the pipe to grep. If find used a single stream, you couldn't separate the noise from the data. This split is the most useful design decision in Unix.
The numeric handles
You'll see numbers in redirections: 2> (stderr), 1> (stdout, default), 2>&1 (merge stderr into stdout). These are file descriptor numbers — direct kernel-level handles. You can open new ones too: exec 3> file opens fd 3, then echo hello >&3 writes to it.