Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I know you can create a file descriptor and redirect output to it. e.g.

exec 3<> /tmp/foo # open fd 3.
echo a >&3 # write to it
exec 3>&- # close fd 3.

But you can do the same thing without the file descriptor:

echo a > "$FILE"

I'm looking for a good example of when you would have to use an additional file descriptor.

share|improve this question
up vote 25 down vote accepted

Most commands have a single input channel (standard input, file descriptor 0) and a single output channel (standard output, file descriptor 1) or else operate on several files which they open by themselves (so you pass them a file name). (That's in addition from standard error (fd 2), which usually filters up all the way to the user.) It is however sometimes convenient to have a command that acts as a filter from several sources or to several targets. For example, here's a simple script that separates the odd-numbered lines in a file from the even-numbered ones

while IFS= read -r line; do
  printf '%s\n' "$line"
  if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt

Now suppose you want to apply a different filter to the odd-number lines and to the even-numbered lines (but not put them back together, that would be a different problem, not feasible from the shell in general). In the shell, you can only pipe a command's standard output to another command; to pipe another file descriptor, you need to redirect it to fd 1 first.

{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt

Another, simpler use case is filtering the error output of a command.

exec M>&N redirects a file descriptor to another one for the remainder of the script (or until another such command changes the file descriptors again). There is some overlap in functionality between exec M>&N and somecommand M>&N. The exec form is more powerful in that it does not have to be nested:

exec 8<&0 9>&1
exec >output12
exec <input23
exec >&9
exec <&8

Other examples that may be of interest:

And for even more examples:

P.S. This is a surprising question coming from the author of the most upvoted post on the site that uses redirection through fd 3!

share|improve this answer
I'd rather say that "most commands have either single or double output channel - stdout (fd 1) and very often stderr (fd 2)". – rozcietrzewiacz Aug 17 '11 at 15:15
Also, could you by the way explain why you use while IFS= read -r line;? The way I see it, IFS has no effect here since you assign value to only one variable (line). See this question. – rozcietrzewiacz Aug 17 '11 at 15:33
@rozcietrzewiacz I've made a mention of stderr, and see the first part of my answer for why IFS makes a difference even if you're reading a into single variable (it's to retain the leading whitespace). – Gilles Aug 18 '11 at 1:26

In the context of named pipes (fifos) the use of an additional file descriptor can enable non-blocking piping behaviour.

rm -f fifo
mkfifo fifo
exec 3<fifo   # open fifo for reading
trap "exit" 1 2 3 15
exec cat fifo | nl
) &

exec 3>fifo  # open fifo for writing
trap "exit" 1 2 3 15
while true;
    echo "blah" > fifo
#kill -TERM $bpid

See: Named Pipe closing prematurely in script?

share|improve this answer
you dug up one of my old questions :) chad is right, you'll run into a race condition. – n0pe Aug 17 '11 at 11:57

Here's an example of using extra FDs as bash script chattiness control:


log() {
    echo $* >&3
info() {
    echo $* >&4
err() {
    echo $* >&2
debug() {
    echo $* >&5


while [[ $# -gt 0 ]]; do
    case $ARG in
        # More flags
        echo -n
        # Linear args

for i in 1 2 3; do
    fd=$(expr 2 + $i)
    if [[ $VERBOSE -ge $i ]]; then
        eval "exec $fd>&1"
        eval "exec $fd> /dev/null"

err "This will _always_ show up."
log "This is normally displayed, but can be prevented with -q"
info "This will only show up if -v is passed"
debug "This will show up for -vv"
share|improve this answer

Here's yet another scenario when using an additional file descriptor seems appropriate (in Bash):

Shell script password security of command-line parameters

env -i bash --norc   # clean up environment
set +o history
read -s -p "Enter your password: " passwd
exec 3<<<"$passwd"
mycommand <&3  # cat /dev/stdin in mycommand
share|improve this answer

An extra file descriptor is good for when you want to catch the stdout in a variable yet still want to write out to the screen, for instance in a bash script user interface

arg1 string to echo 
arg2 flag 0,1 print or not print to 3rd fd stdout descriptor   
function ecko3 {  
if [ "$2" -eq 1 ]; then 
    exec 3>$(tty) 
    echo -en "$1" | tee >(cat - >&3)
    exec 3>&- 
    echo -en "$1"  
share|improve this answer
I know this isn't a new answer, but I had to stare at this quite awhile to see what it does and thought it would be helpful if someone added an example of this function being used.This one echos and captures the whole output of a command - df, in this case. dl.dropboxusercontent.com/u/54584985/mytest_redirect – Joe Oct 19 '15 at 5:03

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.