How to use the POSIX standard file descriptors stdin, stdout and stderr

(, en)

This concept is older than I am, from times where things were much simpler. You want to figure out what standard input (stdin), standard output (stdout) and standard error (stderr) are? Let’s start with basic concepts:

  1. Most Linux or Unix systems adhere to the POSIX standard.
  2. The POSIX standard defines (among other things) three standard file descriptors: stdin, stdout and stderr.

What is a file desciptor?

File descriptors typically have non-negative integer values, with negative values being reserved to indicate “no value” or error conditions. – Wikipedia

To summarise: if you “open” a file, you get an integer back, a file descriptor. Some default file descriptors are usually available. They serve as communication channels between a process and its environment, aka your console/terminal.

file descriptor name
0 stdin
1 stdout
2 stderr

If you run ls, it prints the output to your terminal, using stdout.

$ ls -l
total 24
-rw-r--r--  1 jwb  staff   6  5 Nov 00:06 a
-rw-r--r--  1 jwb  staff  20  5 Nov 00:06 b
-rw-r--r--  1 jwb  staff  37  5 Nov 00:07 c

You can also send data to a process via stdin and some commands send error messages to stderr.

standard fds

Redirection

You can redirect these “streams” to (and from) files or other processes. In bash it looks like this:

# redirect stdin from a file to command; and stdout and stderr of a command to files
command <stdin.txt 2>stderr.txt >stdout.txt

You can even redirect one stream into another. Here we redirect stderr to stdout which then gets written to stdout_and_stderr.txt.

command >stdout_and_stderr.txt 2>&1

Be aware, the order is important! The command below sends stdout to the file, but stderr is redirected to stdout.

command 2>&1 >stdout_only.txt

When is this useful? Nearly never, except you want to mute stdout and continue (aka “pipe”, see further below for explanation) with stderr:

command 2>&1 >/dev/null | grep ...
# example:
ls -z 2>&1 >/dev/null | grep invalid

A detailed explanation you can find in the Redirections chapter of the bash manual.

Note that zsh is behaving slightly different. You have to unset the multios option first:

# zsh-specific
unsetopt multios
ls -z 2>&1 >/dev/null | grep invalid

Pipelines

A pipeline is a sequence of one or more commands separated by one of the control operators | (the pipe symbol) or |&. – bash manual

We’ll focus on |. Here we pipe stdout of the 1st command to stdin of the 2nd command:

$ cmd1 | cmd2

How can you visualise it?

pipe

Of course you can mix and match redirection and pipe operations.

Have fun!

See also