This semester I’m teaching a class on Linux/UNIX, and am enjoying it immensely. With every lecture I’m reminded that you simply never stop finding new tools and tricks to use in an O/S that is now well into middle age.

One of my midterm questions from last week was a basic query regarding filename expansion under bash:

Write a command to copy files chapt00.txt, chapt01.txt, through chapt15.txt from the current directory to your home directory. Make the command as short as possible.

The answer I was expecting was

cp chapt0[0-9].txt chapt1[0-5].txt

and that is indeed what I got from the majority of the students. Of course a few were confused about the use of character classes and tried to get something like chapt[00-15].txt to work. But one student turned in something a bit more novel:

cp chapt{0[0-9],1[0-5]}.txt ~

My initial reaction was that this was simply a misguided attempt at filename expansion using broken syntax. But I was assured that this worked properly, and a quick look at the bash reference manual showed me the error of my ways. It turns out I was completely overlooking a nice feature of the shell: brace expansion. When the shell encounters a sequence of the format preamble{comma-separated-list}postamble, it iterates through the comma list of tokens inside the brackets and generates a new string for each one. The GNU manual example is for the sequence a{d,c,b}e, which generates a space separated list: ade ace abe.

What this means is what I took to be an incorrect file specification actually generated the sequence chapt0[0-9].txt chapt1[0-5].txt. Since brace expansion occurs before filename expansion, this results in the expected output. So this answer, being more terse than my expected response, is actually more right.

Our machines at school are using bash 3.2. If we upgraded to bash 4, we could use a numerical sequence with brace expansion to get even a better answer. The expression chapt{00..15}.txt should expand to the list of all 16 file names. But bash 4.1 is still only slowly working its way into new distributions, so it may be a while before we can count on that syntax to work everywhere.

The moral of the story, of course, is that no matter how much time you spend working with the UNIX/Linux command line, there is always plenty more to learn. I should be paying UTD to teach this course, not the other way around.