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 }
>
- Why does it expect stdin input?
-
A metacharacter is a character that separates words.
The semicolon and whitespace are both “shell metacharacters”. Why can’t whitespace separate wordsdateand}? Why do we need a semicolon instead of a whitespace for separating the words?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 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 thedatecommand saying that it doesn’t understand “}“. -
{and}are valid arguments to common commands, as seen in point 1. For example,finduses{}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 userIt 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.
Method 2
-
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 >
-
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”
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0