Brizzled

... wherein I bloviate discursively

Brian Clapper, bmc@clapper.org

Recursive Globbing Considered Cool

| Comments

I’ve been using Unix shells for so long that I tend to get locked into a particular way of doing things. I first started using Unix in 1985, so I’ve used a lot of shells, among them the original Bourne Shell; the Korn Shell; the C shell (and its fork, Tcsh); and, of course, Bash.

Every so often, it makes sense to shake up the status quo. To that end, and based on some recommendations, I recently switched from Bash to Zsh. While reading the Zsh documentation, I found that it supports recursive globbing. (Actually, Zsh’s globbing features are even more powerful, but discussing all its globby goodness is beyond the scope of this article.)

Anyone who’s used Ant in the Java world is familiar with recursive globs. With this feature enabled in Zsh (which is the default), you can remove all files ending in .log in all directories in and beneath the current working directory with one simple command:

1
zsh$ rm -f **/*.log

That command is equivalent to the more traditional (and arcane):

1
zsh$ find . -name '*.log' -print0 | xargs -0 rm -f

It never occurred to me to see whether Bash supports this feature. (See previous comment about getting locked into a particular way of doing things.) So, after seeing it in Zsh, I checked Bash. Sure enough, Bash 4 has it, too, but it isn’t enabled by default. You have to set the globstar shell option to enable it.

1
2
3
4
5
6
7
8
9
10
11
bash$ cd /var/log
bash$ shopt globstar
globstar        off
bash$ ls **/*.log
ls: cannot access **/*.log: No such file or directory
bash$ shopt -s globstar
bash$ ls **/*.log
appfirewall.log  kernel.log            secure.log
fsck_hfs.log     launchd-shutdown.log  system.log
hdiejectd.log    mail.log              windowserver.log
install.log      notifyd.log           windowserver_last.log

Reminder to self: Check for new features now and then.

Comments