find has a reputation for being unmemorable. It is not: there are four
shapes, and everything else is a variation on one of them.
Files by name, under one directory
$ find lib -name '*.rb'
lib/pulpmesh.rb
lib/pulpmesh/post.rb
lib/pulpmesh/site.rb
Quote the pattern. Unquoted, the shell expands *.rb against the current
directory first and find receives whatever that happened to match.
Files newer than a reference
$ touch -d '2026-01-01' /tmp/cutoff
$ find src -type f -newer /tmp/cutoff
src/parser.c
src/parser.h
There is no -newerthan '2026-01-01'. A reference file is the interface.
Prune a subtree
$ find . -name node_modules -prune -o -name '*.json' -print
./package.json
./config/tsconfig.json
The -o is doing real work. Without -print on the right side, the default
print applies to both branches and the prune is decorative.
Hand the results to something else
$ find . -name '*.log' -print0 | xargs -0 wc -l
1204 ./build.log
318 ./serve.log
1522 total
-print0 and -xargs -0 travel together. Any pipeline that omits them is one
filename with a space away from doing something surprising.
What I still look up
Every single time: -mindepth, -maxdepth, and which order they have to
appear in relative to the tests. The answer is that they are options, not
tests, so put them first.