I've noticed that {
can be used in brace expansion:
echo {1..8}
or in command grouping:
{ls;echo hi}
How does bash know the difference?
bashshell-script
I've noticed that {
can be used in brace expansion:
echo {1..8}
or in command grouping:
{ls;echo hi}
How does bash know the difference?
Best Answer
A simplified reason is the existence of one character: space.
Brace expansions do not process (un-quoted) spaces.
A
{...}
list needs (un-quoted) spaces.The more detailed answer is how the shell parses a command line.
The first step to parse (understand) a command line is to divide it into parts.
These parts (usually called words or tokens) result from dividing a command line at each meta-character from the link:
Meta-characters: spacetabenter;,<>| and &.
After splitting, words may be of a type (as understood by the shell):
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
Brace expansion
Only if a "brace string" (without spaces or meta-characters) is a single word (as described above) and is not quoted, it is a candidate for "Brace expansion". More checks are performed on the internal structure later.
Thus, this:
{ls,-l}
qualifies as "Brace expansion" to becomels -l
, either asfirst word
orargument
(in bash, zsh is different).But this will not:
{ls ,-l}
. Bash will split on space and parse the line as two words:{ls
and,-l}
which will trigger acommand not found
(the argument,-l}
is lost):Your line:
{ls;echo hi}
will not become a "Brace expansion" because of the two meta-characters ; and space.It will be broken into this three parts:
{ls
new command:echo
hi}
. Understand that the ; triggers the start of a new command. The command{ls
will not be found, and the next command will printhi}
:If it is placed after some other command, it will anyway start a new command after the ;:
List
One of the "compound commands" is a "Brace List" (my words):
{ list; }
.As you can see, it is defined with spaces and a closing
;
.The spaces and ; are needed because both
{
and}
are "Reserved Words".And therefore, to be recognized as words, must be surrounded by meta-characters (almost always: space).
As described in the point 2 of the linked page
Your example:
{ls;echo hi}
is not a list.It needs a closing ; and one space (at least) after {. The last } is defined by the closing ;.
This is a list
{ ls;echo hi; }
. And this{ ls;echo hi;}
is also (less commonly used, but valid)(Thanks @choroba for the help).But as argument (the shell knows the difference) to a command, it triggers an error:
But be careful in what you believe the shell is parsing: