Efficient Finds

Recently, I’ve seen a lot of suggestions along the lines of:

find . -name foo -exec ls -l {} ;

This is incredibly inefficient, because for each and every matching
file, ls will be executed. Fortunately, we can do better by
using xargs. xargs takes a list of lines from stdin
and uses them to build up a command line. It takes special care to not
exceed the maximum command line length by splitting the input up into
multiple commands if it is needed. So, with that knowledge, we can
replace our original command with:

find . -name foo | xargs ls -l

There is one slight problem with this command; it isn’t space-safe.
xargs splits arguments on whitespace, so “file name” will be
incorrectly passed to the command as “file” “name”. Fortunately,
xargs has an option to delimit parameters by the null
character, and as our luck would have it, find has a suitable
option to produce output in this format. This means our command is
now:

find . -name foo -print0 | xargs -0 ls -l

mlocate can do something similar:

locate foo -0 | xargs -0 ls -l

GNU find has one more trick up its sleeve. It has a modified version
of -exec that will do the same thing as xargs, so we could have
written our original command as:

find . -name foo -exec ls -l {} +

Every process is sacred; every process is great. If a process is wasted, God gets quite
irate. Please make sure you try to use one of the latter forms and not the
first form, and make a happy deity. 🙂

10 thoughts on “Efficient Finds

  1. Andreas Metzler
    on said:

    “GNU find has one more trick up its sleeve.[…] -exec ls -l {} +”

    Just for clarification “-exec … +” is not a GNUism. It is part of the Susv3/Posix standard and e.g. the find implementations on *BSD supported this before GNU findutils.

  2. Andreas Metzler
    on said:

    “GNU find has one more trick up its sleeve.[…] -exec ls -l {} +”

    Just for clarification “-exec … +” is not a GNUism. It is part of the Susv3/Posix standard and e.g. the find implementations on *BSD supported this before GNU findutils.

  3. Andreas Metzler
    on said:

    “GNU find has one more trick up its sleeve.[…] -exec ls -l {} +”

    Just for clarification “-exec … +” is not a GNUism. It is part of the Susv3/Posix standard and e.g. the find implementations on *BSD supported this before GNU findutils.

  4. As a side note and interestingly, many people uselessly write the dot: “find . arguments”.
    By default find runs on the current directory so there is no need to specify it: “find arguments” is shorter.
    I was telling it to a friend lately, just as he showed me that I could write “ln myfile” more concisely than “ln -s myfile .” Same stuff.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.