Tag: shell

 

find(1) abuse

A colleague wanted to find all the files that end up *.disp or *.frag. Easy enough, right? In the shell you can say *.{disp,frag}.

$ ls *.{disp,frag}
foo.disp
foo.frag

Except that this doesn’t work with find:

$ find . -name '*.{disp,frag}'

Why not? Because braces aren’t globs, so they’re not supported by find(1).

What can you do instead?

Firstly, you can use the -regex flag.

$ find . -regex '.*\.\(disp\|frag\)'
./foo.disp
./foo.frag

This is particularly awful because find defaults to the emacs style of regexes (which took me ages to remember the details of) and means you end up with leaning toothpick syndrome. And you’re matching the whole filename, not a subset, so you have to have the .* on the front.

The second option is to use find’s expression language. Find THIS FILE or THAT FILE.

$ find . \( -name '*.disp' -or -name '*.frag' \) -print
./foo.disp
./foo.frag

This is a bit more readable, but you have to remember that the parentheses are quoted because the shell likes to munch on them. Overall, it does seem preferable to -regex though.

Like all these things, you can take it too far.