Depth and Pruning
Scope: controlling how deep the walk goes —
-maxdepth, -mindepth — and teaching find to
skip a subtree entirely with -prune, including
the broken prune that silently prints nothing.
Depth, counted from the starting point
Depth is distance from the starting point:
the starting point itself is depth 0, the
entries directly inside a directory start are
depth 1, and so on. -maxdepth n refuses to
test or descend beyond depth n:
$ find tree -maxdepth 1
tree
tree/archive
tree/cache
tree/photos
tree/sizes
tree/subdir
tree/times
tree/perms
tree/emptydir
tree/notes.txt
tree/Notes.TXT
tree/report.md
tree/data.csv
tree/.hidden.txt
tree/empty.txt
tree/meeting notes.txt
tree/o'brien.txt
tree/big.log
tree/link-good
tree/link-broken
The starting point and its immediate contents —
a tree's table of contents. Depth limits are
also how you keep a search cheap: a
-maxdepth 2 sweep of a home directory is a
question about its top level only.
The limit's bite is easiest to see against a
file at a known depth. img3.CR2 lives at
depth 3 — tree(0) / photos(1) / raw(2) /
the file(3):
$ find tree -maxdepth 2 -name '*.CR2'
[no output, exit 0]
$ find tree -name '*.CR2'
tree/photos/raw/img3.CR2
Silent, exit 0, and correct: the walk never reached the file. A search that "should have found it" with a depth limit aboard is usually this, arithmetic and nothing more sinister.
-mindepth n is the mirror: entries shallower
than n are passed over entirely (the walk
still descends through them). Its everyday
use is skipping the starting point itself —
or, as here, asking about a subtree's
contents' contents:
$ find tree/photos -mindepth 2
tree/photos/raw/img3.CR2
Depth 0 is photos, depth 1 is raw and the
two jpgs, so depth 2 leaves exactly the raw
file. Both depth tests are global options,
not tests: they govern the whole walk
whichever entries they stand beside, and the
convention — write them immediately after the
starting points, before any test — is worth
following even where find tolerates them later
in the expression, because the reader of your
command will read them where they expect to
find them.
Pruning: don't go in there at all
A depth limit can't express "everything,
except that folder." -prune can: when the
walk reaches an entry the tests before it
match, -prune returns true and, if the entry
is a directory, the walk does not descend
into it. Its canonical shape uses chapter
6's machinery, and both moving parts are
load-bearing:
find tree -path 'tree/cache' -prune -o -type f -print
Reading left to right: at each entry, either
it is the cache directory — prune it, job done
for that branch — or (-o) it isn't, and
the right-hand side applies: files get
printed. The cache specimens exist to be
skipped:
$ find tree -name '*.tmp'
tree/cache/junk1.tmp
tree/cache/junk2.tmp
and under the prune, a full file listing of the tree has 37 entries and neither of them:
$ find tree -path 'tree/cache' -prune -o -type f -print
tree/archive/recent.log
tree/archive/old.log
tree/archive/ancient.log
tree/photos/raw/img3.CR2
...
tree/big.log
[37 lines; no tree/cache entry appears]
Why the -o version works: when the cache
directory matches the left side, -prune
makes that side true, the OR is satisfied,
and the right side — the print — is never
evaluated for it. For everything else the
left side is false, evaluation falls through
to the right, and matching files print.
Now the broken form, which replaces -o with
adjacency — AND:
$ find tree -path 'tree/cache' -prune -type f -print
[no output, exit 0]
Nothing. Not "everything but the cache" —
nothing at all, exit 0. The expression is
now one AND chain: -path and -prune and
-type f and -print. The only entry
satisfying -path 'tree/cache' is the cache
directory itself; it is not a regular file,
so the chain fails for it; every other entry
fails -path. No entry reaches -print.
The prune ate the output, and exit 0 kept the
secret. This is the second member of the
series' silent-silence family (chapter 6's
half-bound -print was the first): when find
prints nothing, the expression — not the
disk — is the first suspect.
One more property worth knowing: -prune on
a file does nothing special — it evaluates
true and the walk continues; pruning is about
descent. And a pruned directory is still
itself evaluated by the rest of the left side
only — in the canonical shape it is never
printed. If you want the pruned directory
named too, that is a second search, or a
deliberate second branch of the OR — write
it knowingly.