24 August 2004
Redirecting stdout and stderr
By default, each Unix process has 3 file descriptors (FDs) assigned to it, 0, 1 and 2; these are known as stdin, stdout, and stderr respectively. They are normally connected to your terminal: stdin is the keyboard; stdout and stderr are your screen.
Each of these represents a stream that can be redirected to other places, such as files or pipes. The output streams, stdout and stderr can be combined and sent to the same place, or directed to different locations.
If you redirect stdout (FD1) to a file, stderr (FD2) will still go to your screen.
$ ls -ld /home /qwerty ls: /qwerty: No such file or directory drwxr-xr-x 11 root root 4096 Jul 11 02:58 /home
If we redirect stdout to the bit bucket, the stderr will still be sent to the screen:
$ ls -ld /home /qwerty 1>/dev/null ls: /qwerty: No such file or directory
(NOTE: the 1
can be left off; >xxxx
implies 1>xxxx
.)
Similarly, if we redirect stderr to the bit bucket, the stdout will still be sent to the screen:
$ ls -ld /home /qwerty 2>/dev/null drwxr-xr-x 11 root root 4096 Jul 11 02:58 /home
Or we can redirect both stderr and stdout to the bit bucket:
$ ls -ld /home /qwerty >/dev/null 2>/dev/null
This works with /dev/null, which isn't a real file, but redirecting both stdout and stderr to the same file individually will not work, as both redirections truncate the file:
$ ls -ld /home /qwerty >/tmp/xxx 2>/tmp/xxx
(The full explanation is too technical for this tip, but it is akin to redirecting output to the same file as the input.)
To redirect both stdout and stderr to the same file, we redirect one stream to the file, then redirect the other to the first stream:
$ ls -ld /home /qwerty >/tmp/xxx 2>&1
The order of the redirections is important. This will send stderr to the terminal and stdout to the file /tmp/xxx:
$ ls -ld /home /qwerty 2>&1 >/tmp/xxx
Sending stderr to stdout attaches the stream to wherever stdout is pointing at the time of the redirection. It is as if stdout and stderr are variables; you are doing the equivalent of:
## the defaults stdout=screen stderr=screen ## redirect stderr stderr=$stdout ## redirect stdout stdout=/dev/null
Now, stdout=/dev/null, and stderr=screen.
If you change the order, the result is different:
## the defaults stdout=screen stderr=screen ## redirect stdout stdout=/dev/null ## redirect stderr stderr=$stdout
Now, stdout and stderr are both pointing to /dev/null.
Modified 18 Nov 2021