Originally published at commandinline.com.
The find command searches a directory tree by name, type, time, size, permissions, or any combination — and runs an action on every match. It is the most powerful filesystem tool on Linux, and the one that rewards memorizing a few core flags. This sheet maps the flags to real tasks and pairs with locate for fast database queries and find -exec deep dive.
Quick Reference
find takes a path, a series of expressions (filters), and optionally an action. The default action is -print. Expressions combine with implicit AND; use -o for OR and ! or -not for negation.
Syntax & Common Options
Form: find [PATH...] [EXPRESSION].
find . -name '*.log' # by name
find /etc -type f # files only
find / -type d -name nginx # directories named nginx
find . -mtime -1 # modified in the last 24h
find . -size +100M # bigger than 100 MB
find . -perm /u+w # any user-write set
find . -name '*.tmp' -delete # deletion action
find . -type f -exec wc -l {} + # batched exec
find . -name node_modules -prune # do not descend into node_modules
Syntax
Path first, then expressions. Expressions before -name are options (e.g., -maxdepth); after are tests and actions.
find . -maxdepth 2 -type f -name '*.py'
find . \( -name '*.log' -o -name '*.tmp' \) -delete
Quick Reference Table
The most-used tests and actions.
Tests:
-name PATTERN glob match (case sensitive)
-iname case-insensitive
-type f|d|l|c|b|p|s file type
-size +N|-N c|k|M|G size (c=bytes, M=MiB)
-mtime ±N modified N*24h ago (- newer, + older)
-mmin ±N minutes
-newer FILE modified more recently than FILE
-perm /MODE any of these mode bits set
-perm -MODE all of these mode bits set
-user NAME by owner
-group NAME by group
-empty empty file or dir
-path PATTERN match full path
Actions:
-print default; print path
-print0 NUL-separated for xargs -0
-delete remove matched files
-exec cmd {} \; one cmd per match (slow)
-exec cmd {} + batched (fast)
-prune do not descend into matched directory
Common Flags
Two patterns dominate: filter by name+type, then act with -exec ... + or -delete.
# Delete logs older than 14 days
find /var/log -type f -name '*.log' -mtime +14 -delete
# Run a command on each match (batched is much faster)
find . -name '*.py' -exec wc -l {} +
Practical Examples
Real-world hunts.
# Files modified in the last hour
find /var/log -mmin -60
# All world-writable files (security audit)
find / -xdev -type f -perm -o+w 2>/dev/null
# Empty directories
find . -type d -empty
# Find and grep (NUL-safe)
find . -type f -name '*.conf' -print0 | xargs -0 grep -l TLS
# Skip noisy directories
find . \( -name node_modules -o -name .git \) -prune -o -type f -name '*.js' -print
# Files larger than 1 GB
find / -xdev -type f -size +1G 2>/dev/null
# Files newer than another (rebuild trigger)
find src -newer build/.last -type f
Tips and Tricks
Patterns from production scripts.
# Stay on one filesystem (do not cross mount points)
find / -xdev ...
# NUL-safe pipeline
find . -type f -print0 | xargs -0 sha256sum
# Group expressions with escaped parens
find . \( -name '*.bak' -o -name '*.tmp' \) -delete
# Time precision: use -newermt for human dates
find . -newermt '2024-01-01' ! -newermt '2024-02-01'
Common Pitfalls
-
find: paths must precede expression — you placed an option after a test. Move
-maxdepth,-mindepth, etc. before any-name/-typetests. -
find: missing argument to -exec — you forgot the terminator.
-execends with\;(one cmd per match) or+(batched).
Pro Tips
- Always prefer
-exec ... +over-exec ... \;for batched commands — orders of magnitude faster on big trees. - Use
-pruneinstead of post-grep filtering to skipnode_modules,.git, etc. — find never descends, saving I/O. - For regex on full paths, use
-regexwith-regextype posix-extended;-nameonly matches the basename. - Pair
-print0withxargs -0when filenames may contain spaces or newlines.
Related Commands
Try the -prune trick on a project with node_modules — find finishes in seconds where it used to crawl, and the syntax sticks immediately.
Top comments (0)