Computer Science Atlas
Snippets

Bash: Redirect stdout and stderr

February 4, 2021|Updated April 16, 2021
 
Table of Contents

stdout 1 and stderr 2

On Linux and other Unix-like / POSIX operating systems, the two standard streams to which programs can send output are:

In addition to their names, you can also refer to these streams by their POSIX file descriptor numbers: - 1 for stdout - 2 for stderr

Normally when you run a program in a terminal window, both stdout and stderr output show up on screen.

Redirect to File

But what if you would rather save the output to a file? Bash (along with other shells) provides a redirect operator > to change where the output gets sent. The syntax looks like:

bash
[source] > [destination]
[source] > [destination]

You can also leave out the spaces:

bash
[source]>[destination]
[source]>[destination]

Now let's take a look at some examples of the operator in action. In the examples, we'll assume that you want to redirect the output of a program called cmd to files on disk (out.log and/or err.log).

bash
cmd 1>out.log            # Redirect stdout to out.log
cmd >out.log             # Same as above (1 = stdout is implied)
cmd > out.log            # Same as above (spaces don't matter)
cmd 2>err.log            # Redirect stderr to file err.log
cmd 1>out.log 2>err.log  # Redirect stdout to file out.log, \
                         #          stderr to err.log
1
2
3
4
5
6
cmd 1>out.log            # Redirect stdout to out.log
cmd >out.log             # Same as above (1 = stdout is implied)
cmd > out.log            # Same as above (spaces don't matter)
cmd 2>err.log            # Redirect stderr to file err.log
cmd 1>out.log 2>err.log  # Redirect stdout to file out.log, \
                         #          stderr to err.log

If you want to send output to multiple destinations, such as both to a file and the terminal screen simultaneously, you won't be able to accomplish that using > — instead, you'll need to enlist the help of a utility called tee.

Combining Output

Notice in the last line of the examples above, you're redirecting stdout and stderr to different files. In this case, the filenames must be different (>out.log 2>out.log does not work).

To combine their output and redirect to a single file, you have to use the reference operator & followed by the number of the file you want (i.e., &1 for stdout, &2 for stderr). Below are some examples.

bash
cmd 2>&1                 # Redirect stderr to stdout
cmd 1>&2                 # Redirect stdout to stderr
cmd 1>combined.log 2>&1  # Redirect stdout and stderr to file combined.log
1
2
3
cmd 2>&1                 # Redirect stderr to stdout
cmd 1>&2                 # Redirect stdout to stderr
cmd 1>combined.log 2>&1  # Redirect stdout and stderr to file combined.log

In the last line, >combined.log sends stdout to file combined.log, and 2>&1 sends stderr to stdout, resulting in everything going to file combined.log.

Silence Output: /dev/null

On Linux and many other systems, you can also redirect output to a special file called /dev/null ("null device") which takes output but doesn't send it anywhere. It provides a way to hide output from a program on screen, but also not save it to any file on disk.

bash
cmd 1>/dev/null       # Silence stdout
cmd > /dev/null       # Same as above (1 is implied)
cmd 2>/dev/null       # Silence stderr
cmd 1>/dev/null 2>&1  # Silence both stdout and stderr
cmd > /dev/null 2>&1  # Same as above (1 is implied)
1
2
3
4
5
cmd 1>/dev/null       # Silence stdout
cmd > /dev/null       # Same as above (1 is implied)
cmd 2>/dev/null       # Silence stderr
cmd 1>/dev/null 2>&1  # Silence both stdout and stderr
cmd > /dev/null 2>&1  # Same as above (1 is implied)

Order Matters

Note that the left-to-right order of redirections matters. The command:

bash
cmd > /dev/null 2>&1
cmd > /dev/null 2>&1

does two things in this order: 1. > /dev/null: redirects stdout to /dev/null; and then 2. 2>&1: redirects stderr to whereever stdout is going, which is now /dev/null.

As a result, you will not see any output (i.e., both stdout and stderr are silenced).

However this command:

bash
cmd 2>&1 > /dev/null
cmd 2>&1 > /dev/null

does two things in this order:

  1. 2>&1: redirects stderr to whereever stdout is going, which currently is just the terminal output; and then
  2. > /dev/null: redirects stdout to /dev/null. stderr is not changed, and will still send output to the terminal.

As a result, this command will display stderr output, but not stdout.

References

See Also