3

The Bash Manual says

{ list; } 

Placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created. The semicolon (or newline) following list is required.

The braces are reserved words, so they must be separated from the list by blanks or other shell metacharacters.

The parentheses are operators, and are recognized as separate tokens by the shell even if they are not separated from the list by whitespace.

If I remove the semicolon, like this:

$ { date }
>
  1. Why does it expect stdin input?

  2. A metacharacter is a character that separates words. The semicolon and whitespace are both "shell metacharacters". Why can't whitespace separate words date and }? Why do we need a semicolon instead of a whitespace for separating the words?

1
  • Apparently this is "due to historical reasons." I'd venture a guess it has something to do with how bash interprets function definitions or brace expansion
    – Eli Heady
    Mar 4, 2016 at 21:57

2 Answers 2

5
  1. It's waiting for the closing }. You've entered a list with one command, date }, and a newline, so you're still inside the command group and can either add another command to the list or terminate it.

    So it's not waiting for standard input (exactly), it's waiting for you to complete the command you started on the first line. If you enter } here, you'll (probably) get an error from the date command saying that it doesn't understand "}".

  2. { and } are valid arguments to common commands, as seen in point 1. For example, find uses {} as an argument.

    Specifically, only exactly "{" and "}" are reserved words. Reserved words in the shell only matter when they're given exactly as an entire word of their own, and only where they're specifically expected. The most important place they're expected is at the start of a command.

    The semicolon or newline means that } appears at the start of the next command in the list, where it can be recognised as a reserved word and given its special treatment. This is specified by POSIX for the shell grammar:

    This rule also implies that reserved words are not recognized except in certain positions in the input, such as after a <newline> or <semicolon>; the grammar presumes that if the reserved word is intended, it is properly delimited by the user

    It would be annoying if "then", another reserved word, couldn't be used as a normal word, so that basically makes sense. ( and ), by contrast, are operators, can appear anywhere, and need to be escaped if they're used for their literal values. This is essentially a historical artefact, and given a do-over perhaps a more consistent choice would be made in one direction or another, or perhaps a more complex parser would be mandated.


For Bash in particular, braces for command grouping also need to be distinguished from braces for brace expansion, and the parser makes an assumption that you're unlikely to be brace-expanding a command that starts with a space.

There is a choice whether to maintain corner-case historical compatibility or not, and some other shells, such as zsh, have cleverer parsers and are able to deal with { date } with the meaning you intended.

4
  • Thanks. Does your quote from POSIX mean that all the reserved words appear after a newline or semicolon? What about the reserved words in and ]] which don't appear after a newline or semicolon?
    – Tim
    Mar 21, 2016 at 0:36
  • @Tim "such as" implies that there are other locations, including the second word after for. ]] is not a POSIX reserved word, but Bash treats it as a keyword that is expected somewhere after [[. Mar 21, 2016 at 0:46
  • "The semicolon or newline means that } appears at the start of the next command in the list". Since there must be a semicolon before }, is } itself a clause with empty command? Must the clauses in a command be separated by a semicolon or newline?
    – Tim
    Mar 21, 2016 at 0:54
  • Items in a command list must be separated by semicolons or newlines. Mar 21, 2016 at 0:58
1
  1. It is waiting for you to complete the command. The same that happens if you write an incomplete if or while or others:

    $ if date
    >
    
  2. The command is clearly defined in the manual: A { list; } is a compound command:

    Compound Commands

    { list; } list must be terminated with a newline or semicolon.

    It is clearly stated there: "terminated with a newline or semicolon"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .