Don't do This With 'find' - part 1
Hell is other peoples code. – Not quite Sartre.
I don’t mind using other peoples code. I’ll even submit patches if I
find a problem, but discovering the same mistakes in almost half-a-dozen
projects is enough to drive me insane. Here are three common red flags
involving the find
command and how to get around them:
If you want to be portable, don't use GNU/Linuxisms.
Compare these two commands -find -name "*.log"
# not portable
find . -name "*.log"
# works everywhere
The first one works with GNU find so it’s fine for (almost) all Linux distributions. It doesn’t work on older Solaris, HPUX or AIX machines and saves one dot. Lesson: specify your paths.
Know what happens when you match nothing.
The first example (shown below) works fine as long as it matches. If
the find
doesn’t return anything you get a syntax error.
find . -name "*.tmp" | xargs rm
# pray for a .tmp file
find . -name "*.tmp" | xargs -r rm
The second example exits silently if there is nothing for it to do. As
noted by Dave
Cantrell, the -r
option is a GNUism so be careful where you
use it. You can also get around this by using find options -exec foo
instead of xargs. But that comes with its own baggage. Lesson: Plan for
errors.
If you're using GNU/Linuxisms then use them properly.
The GNU utilities add a number of powerful and convenient options. If you’ve decided that your script only cares about Linux use them and save a lot of hassle.
find . -ls | awk '{ printf("%s %s %d\n", $NF, $5, $7) }'
# horrible
find . -printf "%p %u %s\n"
# better
The first example is (possibly) more portable but it’s horrible. And not
something you want to see in an init script. The second one is tied to
newer versions of find but is much clearer to read, once you’ve looked up
the escapes using man find
. Lesson: Know your options.