Skip to content

syntax: support {varname} redirects #719

Closed

Description

@jmcantrell

The shfmt tool altering the following valid code, making it invalid:

coproc foo {
    echo test
}

exec {foo[1]}>&-  # converts to: exec {foo[1]} >&-

Activity

  1. mvdan commented on Aug 16, 2021

    @mvdan
    Owner

    I'm not sure I follow what the exec line is doing. What's the syntax there, and where is it documented?

  2. jmcantrell commented on Aug 22, 2021

    @jmcantrell
    Author

    It's closing the file descriptor stored at index 1 of the foo array. The previous coproc command puts file descriptors into the array.

    The syntax for both closing a file descriptor and providing the file descriptor using a variable are described in the second paragraph here: https://www.gnu.org/software/bash/manual/bash.html#Redirections

    And since there can't be any space between the file descriptor and the redirection, it produces the error.

  3. mvdan commented on Aug 31, 2021

    @mvdan
    Owner

    Ah I see, thank you. I was not aware you could close file descriptors stored inside a variable or array. So the parser indeed thinks that you wrote exec {foo[1]} >&-. This will require a bit of an internal refactor to add support for the syntax.

    For my own convenience, here's the relevant bit of the docs:

    Each redirection that may be preceded by a file descriptor number may instead be preceded by a word of the form {varname}. In this case, for each redirection operator except >&- and <&-, the shell will allocate a file descriptor greater than 10 and assign it to {varname}. If >&- or <&- is preceded by {varname}, the value of varname defines the file descriptor to close. If {varname} is supplied, the redirection persists beyond the scope of the command, allowing the shell programmer to manage the file descriptor’s lifetime manually.

  4. jippi commented on Feb 10, 2024

    @jippi

    I just got hit by this one as well 😄 Is there a way to disable this behavior for a file or a line? currently it blocks any usage of shfmt due to breaking flock usage like this

    exec {lock_fd}>"$file"
    # (...)
    exec {lock_fd}>&-

    being turned into

    exec {lock_fd}>"$file"
    # (...)
    exec {lock_fd} >&-  # notice the space here

    Perhaps some other workaround?

  5. changed the title [-]shfmt is changing some valid code into invalid code[/-] [+]syntax: support {varname} redirects[/+] on Feb 18, 2024
  6. c0m1c5an5 commented on May 6, 2025

    @c0m1c5an5

    @jippi For now, a workaround is to eval your command as a string:

    eval 'exec {lock_fd}<&-'
  7. added a commit that references this issue on Aug 13, 2026
    53888e6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions