7

Why can it be used only 1 time when we open the file descriptor ourselves and redirect it to stdin? Please take a look at the example below to understand what I want to say. After reading it once with the cat command, the file is not read via the same file descriptor for the second time.

└─$ exec 6< input.txt
└─$ cat <&6
i am just string
and another string..
└─$ cat <&6
└─$
13

To print the file, the first cat has to read it until the end. exec 6< input.txt causes the shell to hold the file descriptor until the shell dies or closes it, so the file offset still points to the end of the file when the second cat is invoked, which thus writes nothing to stdout.

If on a Linux-based system, you can see that happening by peeking into the file descriptor info:

echo "File contents" > input.txt
exec 6< input.txt
cat "/proc/$$/fdinfo/6"
cat <&6
cat "/proc/$$/fdinfo/6"
cat <&6

If you execute that script, you will get something like

pos:    0
flags:  0100000
mnt_id: 113
File contents
pos:    14
flags:  0100000
mnt_id: 113

confirming that the offset (pos) is not 0 when the second cat is executed, but instead points to its end.

To reset the offset, you can add another exec 6< input.txt in between the cats.

2
  • 2
    ksh93 and zsh can rewind ksh93 has a exec <#((0)) to rewind. And zsh has sysseek 0 (in the zsh/system module), and you can always execute another command to do the lseek(). – Stéphane Chazelas Dec 30 '20 at 13:52
  • 2
    Yes, you can do exec 3<#((0)) or 3>#((0)) like with other redirection operators. – Stéphane Chazelas Dec 30 '20 at 16:19

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.