Hi! Please consider following me on twitter: @hanekomu.
2010年05月28日
bash brace expansion
Last time we looked at bash parameter expansion. Now I would like to talk about bash brace expansion. This is mainly a blog about Perl, but Unix tools like shells and editors are part of a Perl programmer's life as well, so from time to time I'll write about those tools too.
Brace expansion in bash is a way of generating strings. The most general form is a list of strings within braces, separated by commas. There can be other strings before and/or after the braces; they will be included in all variations. For example:
$ echo {foo,baz,baz}
foo baz baz
$ echo prefix-{foo,bar,baz}-suffix
prefix-foo-suffix prefix-bar-suffix prefix-baz-suffix
$ for i in {foo,bar,baz}; do echo $i; done
foo
bar
baz
Brace expansion can be turned on and off using bash's B option.
+B turns brace expansion off, -B turns it back
on.
$ set +B
$ echo {foo,baz,baz}
{foo,baz,baz}
$ set -B
$ echo {foo,baz,baz}
foo baz baz
Here are some easy examples that show what is possible:
$ echo foo{,,,}
foo foo foo foo
$ echo {1..3}{1..3}{1..3}
111 112 113 121 122 123 131 132 133 211 212 213 221 222
223 231 232 233 311 312 313 321 322 323 331 332 333
$ echo {foo,bar,baz}{1..3}
foo1 foo2 foo3 bar1 bar2 bar3 baz1 baz2 baz3
$ echo {foo{1..3},bar{4..6},baz{7..9}}
foo1 foo2 foo3 bar4 bar5 bar6 baz7 baz8 baz9
$ cp /some/very/long/path/to/my.conf{,.bak}
cp /some/very/long/path/to/my.conf /some/very/long/path/to/my.conf.bak
$ mkdir -p /Foo-Bar/{bin,lib,eg,t}
mkdir -p /Foo-Bar/bin /Foo-Bar/lib /Foo-Bar/eg /Foo-Bar/t
$ mv foo{,-}bar
mv foobar foo-bar
You can also specify ranges using the {from..to} syntax, and
ranges with steps using the {from..to..step} syntax. These ranges
can be numeric or alphabetic.
$ echo {1..5}
1 2 3 4 5
$ echo {5..1}
5 4 3 2 1
$ echo {3..-3}
3 2 1 0 -1 -2 -3
$ echo {1..10..2}
1 3 5 7 9
$ echo {a..e}
a b c d e
$ echo {e..a}
e d c b a
$ echo {a..z..2}
a c e g i k m o q s u w y
One typical use for brace expansion is to tell wget or curl to download several files whose URLs conform to a certain pattern:
$ wget http://example.com/path/to/{014..017}.{html,png}
wget http://example.com/path/to/014.html http://example.com/path/to/014.png
http://example.com/path/to/015.html http://example.com/path/to/015.png
http://example.com/path/to/016.html http://example.com/path/to/016.png
http://example.com/path/to/017.html http://example.com/path/to/017.png
(bash version 4 retains leading zeros; earlier bash versions omitted them.)
I also use brace expansion in my ~/.bashrc to inspect certain
directories to find out whether to they contain bin/,
sbin/ or man/ subdirectories that should be added to
$PATH and $MANPATH:
for d in {/usr,/opt,~}{,/{local,share,local/share,perl,perl/5.*.*}}
do
test -d "$d/bin" && PATH="$d/bin:$PATH"
test -d "$d/sbin" && PATH="$d/sbin:$PATH"
test -d "$d/man" && MANPATH="$d/man:$MANPATH"
done
This effectively iterates over all of these directories:
/usr /usr/local /usr/share /usr/local/share /usr/perl /usr/perl/5.*.* /opt /opt/local /opt/share /opt/local/share /opt/perl /opt/perl/5.*.* ~ ~/local ~/share ~/local/share ~/perl ~/perl/5.*.*
Do you have interesting examples of using the bash brace expansion mechanism?
posted at: 10:12 | path: /dev | permalink | 1 comment | 0 trackbacks
Comments are closed for this story.
Trackbacks are closed for this story.
Justin Davis wrote at 2010-05-29 08:49: