On Linux and other Unix-like / POSIX operating systems, the two standard streams to which programs can send output are:
stdout
) andstderr
).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.
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:
[source] > [destination]
You can also leave out the spaces:
[source]>[destination]
[source]
is 1
for stdout
and 2
for stderr
. If you leave [source]
blank, then stdout
is implied.[destination]
is any Unix file, which includes:stdout
(&1
) or stderr
(&2
);/dev/tcp/
path of a network socket;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
).
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
.
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.
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
.
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.
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) |
Note that the left-to-right order of redirections matters. The command:
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:
cmd 2>&1 > /dev/null
does two things in this order:
2>&1
: redirects stderr
to whereever stdout
is going, which currently is just the terminal output; and then> /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
.