Tuesday Tiny Techie Tip
Bourne Shell Redirection
Last week I talked about
redirection in csh(1). At the end of the
discussion I pointed out that there's no way to seperately
redirect stderr and stdout, you either redirect stdout to a
file and let stderr go, or redirect both stderr
and stdout, but if you want to redirect just
stderr, you're hosed.
Bourne shell makes this easy.
Bourne shell uses the single digit file descriptors that
will be familiar to UNIX C programmers. By default, stdin
is associated with fd0, stdout with fd1, stderr with fd2.
The other digits are not assigned by default.
In order to redirect input or output, you create
associations between file descriptors and files and between
file descriptors and other file descriptors.
To associate a file descriptor with a file, you do this:
1> file
This associates output to fd1 with the file "file".
Since stdout is already writing to fd1 by default, this
effectively redirects stdout to "file". As in
csh, a double angle bracket indicates that writes
should be appended to the file rather than having the file
initially truncated.
To associate one file descriptor with another, you do this:
2>&1
This says to send anything written to fd2 to the same place
as output to fd1. Since fd1 is stdout, and fd2 is stderr,
this says to send stderr to the same place as stdout. The
underlying mechanism is the dup2(2) system call.
So let's look at how to do various kinds of redirection:
- Redirect stdout to a file
-
$ ls 1> file
$ ls > file
Since the default file descriptor for output redirection is
fd1, the first form can be abbreviated to the second which
is just like csh
- Redirect stdin from a file
-
$ wc 0< file
$ wc < file
Since the default file descriptor for input redirection is
fd0, the first form can be abbreviated to the second which
is just like csh
- Redirect stdin from text
-
$ wc << END
This is some text
that will be counted
by wc(1).
END
Just like csh
- Redirect stderr to a file
-
$ ls 2> file
This redirects just stderr output (associated with fd2) to
the file. stdout is unchanged. Can't be done in csh.
- Redirect both stdout and stderr to a file
-
$ ls > file 2>&1
First the "> file" indicates that stdout should
be sent to the file, then the "2>&1" indicates
that stderr (fd2) should be sent to the same place as stdout
(fd1).
To append to the file, only the stdout redirection must
change since stderr is just hitching a lift on whatever
stdout is doing.
$ ls >> file 2>&1
- Redirect stdout to one file and stderr to another
-
$ ls > file 2> file2
Try doing that in csh! (Actually, it can be done,
but you have to spawn a subshell)
- Pipe one process' stdout to another's stdin
-
$ ls | wc
Just like csh, but note that there is no analog to
the csh "|&". See below for how to
accomplish the same thing in Bourne shell.
- Pipe one process' stdout and stderr to another's stdin
-
$ ls 2>&1 | wc
Here we combine stderr onto the stdout stream, then use
"|" to pipe the result to the next process.
- Combinations
-
$ sed 's/^#//' < file 2> sederr | \
wc -l 2> wcerr | \
awk '{print $NF}' > final 2> awkerr
Here I'm saving the error output from each command in the
pipeline to a separate file ("sederr",
"wcerr", "awkerr"), but letting stdout go
straight through the pipe into the file "final".
Input to sed(1) at the beginning of the pipe is
redirected from the file "file"
Tuesday Tiny Techie Tip -- 15 April 1997
Forward to (04/22/97)
Back to (04/08/97)
Written by Jeff Youngstrom
Up to the TTTT index
Tuesday Tiny Techie Tips are all © Copyright
1996-1997 by Jeff Youngstrom. Please ask permission before
reproducing any of this material.