[Chapter 17] 17.18 Using "Fast find"
Author: Jerry Peek, Tim O'Reilly & Mike Loukides
Date: 1998-08-04T21:38:33Z

#

| Chapter 17 Finding Files with find |

## 17.18 Using "Fast find"

Berkeley added a handy feature to its find command - if you give it a single argument, it will search a database for file or directory names that match. (If your system doesn't have this feature, see the locate utility below.) For example, if you know there's a file named MH.eps somewhere on the computer but you don't know where, type:

>     % find MH.eps
>     /nutshell/graphics/cover/MH.eps

The database is usually rebuilt every night. So, it's not completely up-to-date, but it's usually close enough. If your system administrator has set this up, the database usually lists all files on the filesystem - although it may not list files in directories that don't have world-access permission. If the database isn't set up at all, you'll get an error like `/usr/lib/find/find.codes: No such file or directory`. (If that's the case, you can set up a "fast find" database yourself. Use GNU locate, below, or see article 17.19.)

Unless you use wildcards, fast find does a simple string search, like fgrep (27.6), through a list of absolute pathnames (14.2). Here's an extreme example:

>     % find bin
>     /bin
>     /bin/ar
>        ...
>     /home/robin
>     /home/robin/afile
>     /home/sally/bin
>        ...

You can cut down this output by piping it through grep (27.1), sed (34.24), and so on. All the fast find commands I've used have an undocumented feature, though: they can match shell wildcards (`*`, `?`, `[]`) (15.2). If you use a wildcard on one end of the pattern, the search pattern is automatically "anchored" to the opposite end of the string (the end where the wildcard isn't). The shell matches filenames in the same way.

The difference between the shell's wildcard matching and fast find's matching is that the shell treats slashes (`/`) specially: you have to type them as part of the expression. In fast find, a wildcard matches slashes and any other character. When you use a wildcard, be sure to put quotes around the pattern so the shell won't touch it.

Here are some examples:

- To find any pathname that ends with bin:

  >     % find '*bin'
  >     /bin
  >     /home/robin
  >     /home/robin/bin
  >        ...

- To find any pathname that ends with /bin (a good way to find a file or directory named exactly bin):

  >     % find '*/bin'
  >     /bin
  >     /home/robin/bin
  >     /usr/bin
  >        ...

- Typing `find '*bin*'` is the same as typing `find bin`.

- To match the files in a directory named bin, but not the directory itself, try something like:

  >     % find '*/bin/*'
  >     /bin/ar
  >     /bin/cat
  >        ...
  >     /home/robin/bin/prog

- To find the files in /home whose names end with a tilde (`~`) (these are probably backup files from the Emacs editor):

  >     % find '/home/*~'
  >     /home/testfile~
  >     /home/allan/.cshrc~
  >     /home/allan/.login~
  >     /home/dave/.profile~
  >        ...

  Notice that the fast find asterisk matches "dot files," too.

- The `?` (question mark) and `[]` (square brackets) operators work, too. They're not quite as useful as they are in the shell because they match the slashes (`/`) in the pathnames. Here are a couple of quick examples:

  >     % find '????'
  >     /bin
  >     /etc
  >     /lib
  >     /src
  >     /sys
  >     /usr
  >     % find '/[bel]??'
  >     /bin
  >     /etc
  >     /lib

locate | Unfortunately, not all systems have fast find. Fortunately, the Free Software Foundation has locate. It's similar to fast find, but locate has an advantage: you can have multiple file databases and you can search some or all of them. Locate comes with a database building program.

Because fast find and locate are so fast, they're worth trying to use whenever you can. Pipe the output to xargs (9.21) and any other UNIX command, run a shell or awk script to test its output - almost anything will be faster than running a standard find. For example, if you want a long listing of the files, here are two find commands to do it:

    -d `...`
    % ls -l `find whatever`
    % find whatever | xargs ls -ld

There's one problem with that trick. The fast find list may be built by root, which can see all the files on the filesystem; your ls -l command may not be able to access all files in the list.

- JP

17.17 Duplicating a Directory Tree (No Pathnames with find {} Operator) |  | 17.19 Finding Files (Much) Faster with a find Database