[Chapter 17] 17.23 Finding Files with -prune
Author: Jerry Peek, Tim O'Reilly & Mike Loukides
Date: 1998-08-04T21:38:43Z

#

| Chapter 17 Finding Files with find |

## 17.23 Finding Files with -prune

find has lots of operators for finding some particular kinds of files. But find won't stop at your current directory - if there are subdirectories, it looks there too. How can you tell it "only the current directory"? Use -prune.

> NOTE: If your version of find doesn't have -prune, this won't work. Try GNU find on the CD-ROM.

-prune prunes find's search tree at the current pathname. So, if the current pathname is a directory, find won't descend into that directory for any further searches. The command line looks kind of hairy. Here's one to find all files from the current directory modified in the last 24 hours:

>     % find . \( -type d ! -name . -prune \) -o \( -mtime -1 -print \)
>     ./afile
>     ./cfile

I'll put that into an alias in a minute. First let's try to understand it - once you see the pattern, you'll understand some important things (8.5, 17.12) about find that many people don't. Let's follow find as it looks at a few pathnames.

find looks at each entry, one by one, in the current directory (`.`). For each entry, find tries to match the expression from left to right. As soon as some part matches, it ignores the rest (if any) of the expression.

1. When find is looking at the file named ./afile: The first part of the expression, `\( -type d ! -name . -prune \)`, doesn't match (./afile isn't a directory). So find tries the other part, after the `-o` (or).

   Has ./afile been modified in the last day? In this case, it has - so the `-print` (which is always true) prints the pathname.

2. Next, ./bfile: Like the previous step, the first part of the expression won't match. In the second part, `\( -mtime -1 -print \)`, the file's modification time is more than one day ago. So this part of the expression is false; find doesn't bother with the `-print` operator.

3. Finally, let's look at ./adir, a directory: The first part of the expression, `\( -type d ! -name . -prune \)`, matches. That's because ./adir is a directory (`-type d`), its name is not `.` (`! -name .`)-and so `-prune`, which is always true, makes this part of the expression true. find skips ./adir.

Your find may also have a -maxdepth option that gives the maximum number of directory levels to descend. For example, `find . -maxdepth 0` operates only on the current directory.

Let's put the version with -prune into a couple of aliases. The first one, named find. (with a dot on the end of its name), just prints names with -print. The second alias gives a listing like ls -gilds. They work like this:

>     % find. -mtime -1
>     ./afile
>     ./cfile
>     % find.ls -mtime -1
>     43073   0 -r----  1 jerry    ora        0 Mar 27 18:16 ./afile
>     43139   2 -r-r-r-  1 jerry    ora     1025 Mar 24 02:33 ./cfile

The find. alias is handy inside backquotes (9.16), feeding a pipe, and other places you need a list of filenames. Here are the aliases. The second one, find.ls, uses -ls instead of -print:

>     alias find. 'find . \( -type d ! -name . -prune \) -o \( \!* -print \)'
>     alias find.ls 'find . \( -type d ! -name . -prune \) -o \( \!* -ls \)'

(The Bourne shell versions on the CD-ROM are named Find and Findls because a dot isn't legal in a function name.)

If you don't want the `./` at the start of each name, add a pipe through `colrm 1 2` (35.15) or `cut -c3-` (35.14) to the end of the alias definition.

- JP

17.22 Finding the Links to a File |  | 17.24 Skipping Some Parts of a Tree in find (A More Selective -prune)