3

Content of a file named file

testing 1
testing 2

Command tested

exec 3<> ./tmp
cat file 1>&3 3>&1

Outputs nothing. Why?

I read my command as

cat content in file, then read STDOUT and give it to file descriptor 3 and then take the content from file descriptor 3 and give it's content to STDOUT

Am I reading my command wrong ?

How shall I read my command in order to understand it better and get the output of file


After understanding your answer Stéphane, I tried the following commands

cat file 1>&3 3> ofile

which didn't write the contents of fd 3 (which gets it's content from fd 1 i.e STDOUT) to ofile

but the I tried the following command

cat file 1>&3 && cat <3

which printed the content of fd 3 to the STDOUT.

Why didn't fd 3 write to ofile when fd 3 has the content of fd 1 ?


Stéphane, the command Jesse_b mentioned in the comments below i.e

cat file 3> ofile 1>&3 

works and does write the content of file to ofile but the command

cat file 1>&3 3> ofile

as I mentioned earlier fails to write to ofile.

How did the placement of 1>&3 at the end and at the beginning of 3> ofile affect the output of these two commands ?

  • I don't think that is how any of this works. If you would like your command to read the contents of file to STDOUT you can execute this command: cat file If you want to redirect STDOUT to something else you can do cat file > or cat file 1> – Jesse_b Jul 28 '17 at 21:37
  • When you do 1>&3 you aren't saying "redirect 1 to 3" you are saying "redirect 1 and 3" – Jesse_b Jul 28 '17 at 21:38
  • 1
    Try cat file 3> ofile 1>&3 also I don't think your second command is actually working. I think it's executing: cat file and throwing away 1>&3 && cat <3 – Jesse_b Jul 28 '17 at 22:35
  • I'm not exactly sure how it works but I know if you want to throw away all output you put it at the end like this: command > /dev/null 2>&1 – Jesse_b Jul 29 '17 at 1:31
4

cmd x>&y says: "redirect fd x to whatever resource fd y is redirected to"

So in:

cat 1>&3 3>&1

You're saying that cat's fd 1 (stdout) should go to the same resource as open on fd 3, that is ./tmp open in read+write mode; and then fd 3 to the same resource as open on fd 1, which you've just made to be ./tmp.

So cat will be started with both its fds 1 and 3 redirected to ./tmp. cat doesn't do anything with its fd 3, you can redirect cat's fd 3 to anything you like, it will have no effect.

However it does write the content of file to its fd 1, so you'll find the content of file written at the start of ./tmp.

cat file writes the content of file only once and only to one fd. If you want something that write the content of file twice to two different fds, you'd want tee instead:

In

< file tee ./tmp

tee would write what it reads from its fd 0 (here redirected to file open in read-only mode) to both ./tmp (open in write only mode with truncate) and its fd 1 (stdout).

While it's possible to tell tee to open ./tmp in append mode with -a, you can't tell it to open ./tmp in read+write mode without truncation like 3<> does.

For that, you'd need:

< file tee /dev/fd/3 3<> ./tmp

which would work except on Linux, or resort to using zsh and its builtin teeing facility:

cat < file 3<> ./tmp >&1 >&3 3>&-

With fd 1 being redirected twice, zsh, when the mulltios option is enabled (on by default), would do an internal tee to forward the output to both destinations (by running an internal process that reads cat's output and writes it to both destinations).

The temporary use of fd 3 is to work around the the problem that in

cat < file >&1 1<> ./tmp

zsh would complain with zsh: file mode mismatch on fd 1 as it supposes you want to read from ./tmp.

  • Thank you for clearing why my code didn't work but there's one more problem that I would like you to look into. I have updated my question after reading your answer, please have a look. – GypsyCosmonaut Jul 28 '17 at 22:33
  • @GypsyCosmonaut, see edit that stresses the fact that cat doesn't touch its fd 3, so there's no point trying to make it point to anything. – Stéphane Chazelas Jul 28 '17 at 22:36
  • There's one more problem, updated my question again, please have a look. – GypsyCosmonaut Jul 28 '17 at 23:05
  • @GypsyCosmonaut, redirections are processed from left to right. in cat file 1>&3 3> ofile you're redirecting fd 1 to whatever resource was open on fd 3 (if there was a exec 3<> ./tmp before, then that will be that) and then fd 3 to ofile. So we have 1 goes ./tmp, 3 goes to ofile. cat doesn't do anything with its fd 3, so all you get is an empty ofile because it was open with truncation and nothing was ever written to it. – Stéphane Chazelas Jul 28 '17 at 23:34

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.