[EnglishFrontPage] [TitleIndex] [WordIndex

Brace expansion is one of the substitutions that Bash performs on its commands. It is entirely syntactic in nature (it has no understanding of context). Essentially, it is used as a typographic shortcut, to make commands more concise:

mv foobar.{o,exe} obj

# equivalent to:
mv foobar.o foobar.exe obj

A brace expansion results in one or more words. Any characters outside of the braces are repeated in every word. The braces determine the content that varies across the words.

Brace expansions can use comma-delimited strings, as shown in the example above. As of Bash 3.0, they can also use ranges of letters or numbers. This is known as "sequence expansion":

for i in {1..10} {a..f}; do
  sleep 1
  echo $i

Brace expansion happens before parameter expansion, which makes it nearly impossible to use brace expansion to create lists whose size is only known at run-time.

# won't work!
for i in {1..$n}; do

In the case of simple iteration over integers, an arithmetic for loop should almost always be preferred over brace expansion, because brace expansion pre-expands every argument which can be slower and unnecessarily consumes memory.

for ((i=1; i<=n; i++)); do

In the case of generating argument lists, a loop can also be used to build an array.

pushd ~/music

while ((i<=n)); do
    args+=( @(foo|bar)$((i++)).mp3 )

cmd "${args[@]}"


# zsh or ksh93

$ n=5; echo {1..$n}
1 2 3 4 5

Bash's evaluation order is a mixed blessing. On one hand it allows for the results of brace expansion to be subject to all other substitutions, so that any generated expansions are evaluated:


$ echo $((n++)){1..5}
01 12 23 34 45

# zsh or ksh93

$ echo $((n++)){1..5}
01 02 03 04 05

On the other, it prevents the results of other substitutions from being interpreted as brace expansions, this arguably makes brace expansion slightly safer to have enabled by default, so in Bash, it is. Both can be good or bad depending on what you're trying to accomplish. This is one of the unfortunate compromises.

See Also


2012-07-01 04:05