1

Bash has a feature where it will pick a file descriptor number for you and assign it to a variable.

$ exec {fd}>foo.txt
$ echo "$fd"
11
$ echo "bar" >&$fd
$ cat foo.txt
bar

This feature works great with bash 4.4, but I've encountered a snag with bash 4.2 when I use it inside a function. Here's a minimal demonstration:

$ bash --version | head -1
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
$ (func() { echo 1>&$fd; }; type func)
func is a function
func () 
{ 
    echo &>$fd
}
$ (func() { echo 2>&$fd; }; type func)
func is a function
func () 
{ 
    echo 2>&$fd
}

Notice that in the first test 1>&$fd became &>$fd. If $fd were 11, instead of redirecting to fd 11 it would redirect to a file named 11. However, it's only with stdout. stderr doesn't have this bug, as the second test shows.

Nor does bash 4.4:

$ bash --version | head -1
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
$ (func() { echo 1>&$fd; }; type func)
func is a function
func () 
{ 
    echo 1>&$fd
}

It looks like this is a bug that was fixed. Is that true? And more importantly, can you suggest any workarounds?

  • 1
    Note that in bash, arguments to redirections still undergo word splitting, so you'd still need 1>&"$fd" and with those extra quotes, even bash 5 or the current git head exhibits the bug, so it looks like it's not fully fixed. – Stéphane Chazelas Jun 1 at 7:40
  • even though type func shows echo &>$fd, in my test with 4.2, the function behaves as if it was echo >&$fd. – Stéphane Chazelas Jun 1 at 7:46
0

As a workaround change >& to 1<&. It avoids the bug while preserving the desired behavior. Whether fds are opened for reading or writing doesn't matter when duplicating them. dup2() doesn't care.

$ bash --version | head -1
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
$ (func() { echo 1<&$fd; }; type func)
func is a function
func () 
{ 
    echo 1<&$fd
}
  • This is what I came up with as a workaround. I'm definitely curious if there are other better ones. – John Kugelman Apr 28 at 15:20

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.