The voodoo of bash token expansion

Unlike the stunted Windows command shell (I admit I haven’t tried PowerShell), the bash shell combines the ability to put together many different small utilities with some built-in smarts to offer an incredibly powerful interactive experience.

One of the more handy built-in smarts is bash’s “magic” token expansion. If bash sees one of these while evaluating a statement, it expands it before doing anything else. The most common of these is the asterisk, which expands to everything in the current directory:

maciek@potato:~/bash$ ls
maciek@potato:~/bash$ touch foo bar # touch creates empty files named like the arguments
maciek@potato:~/bash$ echo *
bar foo

One interesting aspect is that if there is nothing in the current directory, the asterisk does not expand:

maciek@potato:~/bash$ rm foo bar
maciek@potato:~/bash$ echo *
*

You can also tell bash that you want a literal asterisk by escaping it with a backslash:

maciek@potato:~/bash$ touch foo bar
maciek@potato:~/bash$ echo *
bar foo
maciek@potato:~/bash$ echo \*
*

One of the more powerful aspects of bash is being able to spawn a subshell with $(...) (the output of the subshell is “injected” wherever the subshell block occurs). The interesting thing in terms of token expansion is that the result of the subshell execution seems to be a candidate for token expansion as well:

maciek@potato:~/bash$ echo $(echo \*)  
bar foo  

However, there are other types of expansions that bash does for you. One of my favorite is brace expansion:

maciek@potato:~/bash$ echo foo{1,2,3}
foo1 foo2 foo3

This is extremely handy for, e.g., moving files nested deep in some directory hierarchy. However, a weird thing seems to happen with brace expansion and the results of subshells:

maciek@potato:~/bash$ echo $(echo foo\{1,2,3\})
foo{1,2,3}

The expansion is ignored. I’m far from a shell scripting expert, but I can’t figure this out. It seems that it should be analogous to the ‘*’ expansion, but it behaves differently. Any ideas?

Advertisements
Posted in programming. Tags: . 1 Comment »