On Monday, November 26, 2012 11:57:33 AM Chet Ramey wrote: > On 11/26/12 8:41 AM, Pierre Gaston wrote: > > On Mon, Nov 26, 2012 at 3:37 PM, Chet Ramey <chet.ra...@case.edu > > <mailto:chet.ra...@case.edu>> wrote: > > > > On 11/23/12 2:04 AM, Pierre Gaston wrote: > > > It seems rather counter intuitive that the fd is not closed after leaving > > > the block. > > > With the normal redirection the fd is only available inside the block > > > > > > $ { : ;} 3>&1;echo bar >&3 > > > -bash: 3: Bad file descriptor > > > > > > if 3 is closed why should I expect {fd} to be still open? > > > > Because that's part of the reason to have {x}: so the user can handle the > > disposition of the file descriptor himself. > > > > . > > I don't see any difference between 3> and {x}> except that the later free > > me from the hassle of avoid conflicting fd > > That's not really an issue. Bash goes to great effort to allow users to > specify fds it is already using internally. > > The user/shell programmer getting a handle to the fd is one benefit. The > ability to use those named fds in operators that don't allow words (e.g. > variable expansions) to replace the explicit file descriptor number is > another. > > David Korn beat all of us in implementing this feature (we first began > discussing it in 2005). I should ask him if he has additional insight. > > Chet >
I believe one of the motivations for named FDs other than automatic FD allocation, and the reason they remain open, was probably to deal with organizing and grouping coprocesses so that you could follow the variable names rather than the FDs directly due to the somewhat awkward way they are manipulated. ksh, mksh, and zsh have almost the same system (except the Zsh "coproc" pipeline modifier replaces Ksh's "|&" list operator) in which you start with an "anonymous coproc" that can only be accessed indirectly through "read -p" and "print -p", until moving the current coproc to a named FD with the special "&p" redirects. After that, and you have a handle on the real FD, you can open a new anonymous coproc and begin interacting with the others through "read -u" and "print -u" instead. Basically: Bash: coproc { ...; }; read -ru "${COPROC}" Everybody else: { ...; } |& { read -ru "$COPROC"; } {COPROC[0]}<&p {COPROC[1]}>&p I suppose the idea was that you could have collections of coprocs organized into arrays held open until you're finished with them. Bash does it without adding all that extra syntax, so the FD assignment feature is less important, with the downside being there are a bunch of incompatible conflicts like the "|&" pipe and "read -p" (unnecessary features IMO, but not a big deal). One potential gotcha in Bash is that RETURN traps execute while exposed to the fds that were redirected during the call to the function, not to the definition. I don't know if that's intentional or whether most people are aware that both sets of redirects are active until returning even if a redirect to the definition hides another made to the call. Since you can only access local variables from a RETURN trap, but the visible FDs are a combination of redirects held open from a execs or named FD assignments, plus redirects to the function call, it could be easy to be surprised if relying upon RETURN to close the right FD especially if variable names from different scopes conflict. $ bash -s <<\EOF f() { trap 'trap - RETURN; cat "/dev/fd/$x" -; exec {x}<&-' RETURN local x : <<<inner {x}<&0 cat "/dev/fd/$x" - } <<<middle f <<<outer EOF inner middle inner outer -- Dan Douglas