Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

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

What does the following script mean?

exec 4<&0 0</etc/XX/cfg
read line1
exec 0<&4

It redirects fd0 to fd4, and "/etc/XX/cfg" to fd0.

So why does read still work, shouldn't that be empty?

share|improve this question
This question may be useful background. – Gilles Apr 10 '12 at 18:13
up vote 5 down vote accepted

It redirects stdin (FD0) to FD4, redirects from /etc/XX/cfg to FD0, reads a line from FD0, and then moves FD4 back to FD0. In short, it saves, replaces, and restores stdin, while reading a line from a file in between.

read line1 < /etc/XX/cfg would be so much easier, but it's impossible to tell if it's a valid replacement based only on the code shown.

share|improve this answer
It doesn't "redirect" fd0 to fd4, it "duplicates" it (using the dup2 syscall), so that reading from either descriptor will have the same effect. Of course, it then overwrites fd0, so you can think of it as "moving" the descriptor, if you like. – ams Apr 10 '12 at 10:56
So if the stream went from the file to fd0 , from fd0 to fd4 , why would reading from fd0 still work ? – warl0ck Apr 10 '12 at 10:59
It doesn't remove the stream from the old FD. Plus, it opens a file on it regardless. – Ignacio Vazquez-Abrams Apr 10 '12 at 11:00
@warl0ck: there's two parts to the first exec. It's only between the two that you can read stdin on both descriptors. Opening the file on fd0 overwrites the old setting, which is why the code saves it on fd4 first. – ams Apr 10 '12 at 11:51
@ams thanks , now it's all clear. – warl0ck Apr 10 '12 at 11:54

To recast this in syscalls (using C):

exec 4<&0 0</etc/XX/cfg

/* Duplicate fd0 as fd4.  */
dup2 (0, 4);

/* Open file on fd0.
   "open" always uses lowest available descriptor, so we don't need to check it. */
close (0);
open ("/etc/XX/cfg", O_RDONLY);

exec 0<&4

/* Close fd0 and duplicate fd4 as fd0.  */
dup2 (4, 0);
share|improve this answer

The way I read this - based on the bash manpage section on REDIRECTION - is that stdin (fd0) is redirected into fd4, then input is taken from /etc/XX/cfg into stdin - which will end up on fd4.

read line1 should then take from fd4 which is then put back to fd0.

A demo might show my meaning a little better and answer "why" you might do this. By adding another line and putting it in a wrapper:

$ vim ./test.sh
exec 4<&0 0</etc/XX/cfg
read line1    # reads from fd4
exec 0<&4
read line2    # reads from fd0

echo $line1 
echo $line2

You can pipe or redirect stdin via test.sh but also read in configuration by redirection, so in the code above I've pulled in values from the "config" (assumption on my part based on the filename - bad :) ), but I can process via stdin as well.


$ ./test.sh < somefile
$ cat somefile | ./test.sh

Hopefully this explains it.

share|improve this answer
I think you've misunderstood: there are no reads from fd4 here. – ams Apr 10 '12 at 12:48
Having read your comment above, I think you're right, I have. – da-architect Apr 10 '12 at 12:54

protected by Community Apr 28 '15 at 13:49

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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