3

I found out I don't totally understand how bashfile descriptors work. I would like to have some guidance here.

I have a scenario where I need to read the content of a file, and for each line of the file, execute anotherread to get the user's selection. So I need an extrafd, and help to do that.

I got the idea from thisanswer and came out with this solution:

#!/bin/bash    while read content <&4; do           echo        read  -p 'Do you want to proceed [y|n] ?' choice         case "$choice" in            ([yY]) bash $content ;;            ([nN]) continue ;;        esac    done 4< a_text_file

What I understand is,the filea_text_file is assigned to file descriptor4, and then bash uses theread built-in to read the content of text filea_text_file by using the file descriptor 4.

But now I realize my understanding is incorrect, as in thebash GNU docs, it says:

[n]<&word

"is used to duplicate input file descriptors. If word expands to one or more digits, file descriptor n is made to be a copy of thatfile descriptor. It is a redirection error if the digits in word donot specify a file descriptor open for input. If n is not specified,this uses the standard input (file descriptor 0)."

So there isduplicating of file descriptors happening. My question is:

  1. What does the above operation have to do with 'duplicate input file descriptor'?
  2. Which file descriptor is being duplicated?
  3. Why does bash need to do that to read the file content using the file descriptor 4?
  4. And please also point out which concept of fd I have gotten totally wrong.

Also, I would be very grateful if anyone could recommend any good online resource that could explain the concept offd well, as I really can't grasp it by just reading the GNU docs.

ilkkachu's user avatar
ilkkachu
148k16 gold badges268 silver badges440 bronze badges
askedyesterday
sylye's user avatar
2
  • Yeah, the answer you linked to glossed over the details of what<&3 does under the hood. The point is thatin effect the redirection hasread read what there is available to be read from fd 3, though under the hood it's a bit messier.read -u 3 would be better. I tried to clarify that answer a bit.Commentedyesterday
  • fds are just the file handles of Unix-land, not that special in the simple cases. Open a file, get an fd, read from/write to the fd, profit. It's the cases about multiple redirections that can screw heads. See e.g.this Q about the order of redirections, but there are others.Commentedyesterday

1 Answer1

10

What does the above operation have to do with 'duplicate input file descriptor'?

read actually reads from file descriptor 0 (the stdin). The<&4 isn't part ofread syntax at all – itdoes not tellread to read from fd#4; rather, it duplicates fd#4 to fd#0 so thatread will have the file available at fd#0 i.e. stdin.

(0 is the default target for<, so<&4 is short for0<&4, if that makes it any clearer.)

It is 'duplication' because the result is thatboth fd#0 and fd#4 now refer to the same thing.

Why does bash need to do that to read the file content using the file descriptor 4?

Most programs expect their input to be provided through file descriptor #0, which is considered the "standard input" or stdin. Bash'sread has the same expectation. The redirection<&4 copies fd #4 to fd #0 for the duration of theread command.

Although in Bash, ksh and zshread actually does have the option to read directly from another fd, using-u:

read -u 4 content

You can do that if you're specifically targeting one of the feature-rich shells and not /bin/sh in general. (Your script currently requests#!/bin/bash so-u will always be available.)

This is not standard and other shells might not necessarily have it in their own versions ofread, so using the< redirection is a more "compatible" method if you're aiming towards general POSIX shell compatibility.

Also, I would be very grateful if anyone could recommend any good online resource that could explain the concept of fd well, as I really can't grasp it by just reading the GNU docs.

File descriptors are not a Bash concept; they're a far more general concept that all programs (and most programming languages) have on Linux or on Unix-like systems in general. So instead, try C docs or Python docs, e.g. what Copen() returns, how a program reads from stdin or writes to stdout, and howdup() anddup2() work (x<&y effectively does adup2(y, x) to clone the FD).

answeredyesterday
grawity's user avatar
7
  • 1
    sourceware.org/glibc/manual/2.42/html_mono/…Commentedyesterday
  • 1
    read <&4 is also a bit convoluted in that it makes Bash actually do the system calls required to copy the fd and close the copy, for each invocation ofread. Whileread -u 4 would just directly read from fd 4.Commentedyesterday
  • read -u is from ksh, which bash (and zsh) copied, it's not specific to bash.Commentedyesterday
  • Notice that using FD#4 and #5 - at least in the Korn Shell -might pose a problem because these two file descriptors (only these!) are used for the coprocess facility (communication with asynchronously running sub-processes).Commentedyesterday
  • @bakuninksh -c 'uname |& exec 3>&- 4>&- 5>&-; cat <&p' works fine for me. That is even if ksh may end-up using fd 4 or 5 internally if they are the first free fd, it takes care of that not interfering with the fd 0 to 9 the user may want to use (by moving those internal fds as needed for instance to higher fd numbers)Commentedyesterday

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.