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:
- What does the above operation have to do with 'duplicate input file descriptor'?
- Which file descriptor is being duplicated?
- Why does bash need to do that to read the file content using the file descriptor 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.
- 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.ilkkachu– ilkkachu2025-10-06 11:51:23 +00:00Commentedyesterday - 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.ilkkachu– ilkkachu2025-10-06 12:02:13 +00:00Commentedyesterday
1 Answer1
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).
- 1sourceware.org/glibc/manual/2.42/html_mono/…choroba– choroba2025-10-06 08:25:32 +00:00Commentedyesterday
- 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.ilkkachu– ilkkachu2025-10-06 10:04:32 +00:00Commentedyesterday read -u
is from ksh, which bash (and zsh) copied, it's not specific to bash.Stéphane Chazelas– Stéphane Chazelas2025-10-06 10:06:02 +00:00Commentedyesterday- 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).bakunin– bakunin2025-10-06 16:45:23 +00:00Commentedyesterday
- @bakunin
ksh -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)Stéphane Chazelas– Stéphane Chazelas2025-10-06 20:06:57 +00:00Commentedyesterday
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.