0

I haven't quite wrapped my head around how to use additional file descriptors. I suspect you could use them to simulate what the tee utility does, viewing a command's output while simultaneously writing it to a file. I also suspect doing so would help me better understand how to use additional file descriptors...

My attempts so far,

date 3>&1 3>file

My thinking was, create 3 as a duplicate of 1 (stdout) and redirect 3 to write to file, thus I have stdout writing to the terminal as usual, and 3 writing to a file.

But this doesn't work. When I cat file, it's empty. Where did I go wrong?

4

A redirection operator changes where output is going (or where input is coming from). 3>&1 means “make file descriptor 3 point wherever file descriptor 1 is currently pointing” (which is the terminal). 3>file means “make file descriptor 3 point to file”. Nothing happened during the brief time fd 3 was pointing to the terminal, so you don't get any terminal output.

In order to obtain the same data in two locations, something needs to copy the data. This is the job of tee. For every byte that it reads, it outputs that byte twice (if given one file argument, plus its standard output).

Don't get bogged down by the fact that >& is sometimes called duplication. What it's duplicating is the file descriptor: 3>&1 duplicates fd 1 to fd 3, meaning that the data going to fd 1 and the data going to fd 3 are getting merged — they're both going to wherever fd 1 was pointing.

If you prefer graphical explanations, see what is meant by connecting STDOUT and STDIN? and How can a command have more than one output?

In any case, your command doesn't output anything on file descriptor 3, so redirecting fd 3 doesn't change anything. The date command writes to its standard output, i.e. fd 1, and you aren't redirecting that.


Zsh has a feature called multios that changes the meaning of output redirection. If there are multiple output redirections for the same command on the same file descriptor, then the first one changes where that descriptor is pointing, but subsequent ones replicate the data to the specified targets. For example, to get output in a file in addition to wherever stdout was pointing, you can use

date >&1 >file

Zsh is doing the job of tee. Note that the order of redirections matter — date >file >&1 would write to file twice, since by the time the >&1 operator is evaluated the standard output of date is already going to file.

1

No, because it doesn't duplicate the output. To duplicate the file descriptors, you also have to output to them twice.

Although you can do it with a loop, like so:

while read l
do
   echo "$l" >&3
   echo "$l" >&4
done

With binary data it will be buggy (zeros chunked out, crlf-s will be converted to lf).

Your example did this:

  1. opened fd 3 to file
  2. cloned fd 1 to in the place of fd 3 (i.e. it closed your previous fd3 and then make fd3 to be an "alternative address" of your previous stdout).

The redirection is essentally a clone, in unix terminology, it is like a hard link. With a 3>&1 suffix to a commant, you will have fd 3 and fd 1 pointing to the same entity (which is now file).

If you have some affinity to C, I would like to check a man 3 dup2, this is exactly what an fd redirection does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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