Differences between revisions 2 and 3
Revision 2 as of 2012-03-30 16:54:43
Size: 2875
Editor: ormaaj
Comment: Add esoteric crap.
Revision 3 as of 2012-03-30 18:13:14
Size: 3051
Editor: ormaaj
Comment: link
Deletions are marked like this. Additions are marked like this.
Line 79: Line 79:
== See Also ==

 * This article is still new. Bash-hackers has a mature one: http://wiki.bash-hackers.org/syntax/expansion/brace Feel free to help improve either or both!

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
done

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
...
done

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 )
done

cmd "${args[@]}"
popd

portability

  • Brace expansion is not specified by POSIX. It was first introduced in csh, but Bash, Zsh, ksh93, and mksh all have similar brace expansion features. mksh doesn't support sequence expansion, and zsh only supports sequence expansion on integers by default, but has many of it's own extensions. ksh93 doesn't enable brace expansion by default, Bash does.

  • Only Bash performs brace expansion first. zsh, ksh93, and mksh evaluate brace expansion immediately before pathname expansion. ksh93 considers it a part of word splitting. This means other shells don't suffer the problem of expanding parameters into brace expansions:

# 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:

#Bash

$ 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


CategoryShell

BraceExpansion (last edited 2014-11-21 22:05:55 by ormaaj)