find
Search a directory tree for files matching criteria
By CMD Script Team · 5 min read · Last updated
find [PATH...] [EXPRESSION]Options
| Flag | Description |
|---|---|
-name PATTERN | Match files by name using shell glob syntax (case-sensitive); use -iname for case-insensitive |
-type f|d|l | Restrict matches to a type: f for regular files, d for directories, l for symlinks |
-size +100M | Match by size; + for greater than, - for less than (suffixes: c, k, M, G) |
-mtime -7 | Match by modification time in days; -7 means modified within the last 7 days, +7 means more than 7 days ago |
-exec CMD {} \; | Run CMD on each match, with {} replaced by the matched path; \; runs the command once per file |
-exec CMD {} + | Same as -exec but batches multiple matches into fewer command invocations, like xargs |
-maxdepth N | Limit recursion to N directory levels below the starting path |
-delete | Delete matched files; must come after all filtering expressions |
Distribution compatibility
- Ubuntu
- Debian
- Fedora
- Arch
- macOS (BSD find, some flag syntax differs)
What it does
find searches a directory tree, starting from one or more given paths, for files and
directories that match a set of criteria you specify: name, type, size, modification
time, permissions, ownership, and more. Unlike tools that rely on a prebuilt database,
find walks the actual filesystem every time it runs, so its results always reflect the
current state of disk — at the cost of being slower than an indexed search for very large
trees.
Beginner examples
find .— list every file and directory under the current directoryfind /etc -name "*.conf"— find files ending in.confunder/etcfind . -iname "readme*"— case-insensitive name matchfind . -type d— list only directoriesfind . -type f— list only regular files (no directories, symlinks, etc.)
find /home/user -name "*.jpg"
Advanced examples
- Find files over 100MB anywhere on disk:
find / -type f -size +100M - Find files modified in the last 7 days:
find /var/log -mtime -7 - Find files not modified in 30+ days and delete them:
find /tmp -name "*.tmp" -mtime +30 -delete - Limit recursion depth to avoid descending too far:
find . -maxdepth 2 -name "*.log" - Run a command on every match, one invocation per file:
find . -name "*.sh" -exec chmod +x {} \; - Batch matches into fewer invocations (faster):
find . -name "*.o" -exec rm {} + - Combine multiple conditions:
find . -type f -name "*.py" -newer reference.txt
find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null
Common mistakes
- Forgetting that
-exec CMD {} \;runs the command once per file, which is slow for thousands of matches — use-exec CMD {} +or pipe toxargsinstead. - Putting
-deletebefore other filters in the expression;findevaluates expressions left to right, so-deletemust come last or it can delete more than intended. - Running
find /without redirecting stderr, so the output is cluttered with "Permission denied" noise — add2>/dev/nullwhen searching system-wide as a non-root user. - Confusing
-mtime -7(modified less than 7 days ago) with-mtime +7(modified more than 7 days ago) — the sign matters and is easy to get backwards. - Expecting
findto be as fast aslocateon huge filesystems;finddoes a live scan every time, whilelocatereads a prebuilt index.
Tips
- Use
-maxdepthto bound how deepfindrecurses when you only care about the top levels of a tree — this can dramatically speed up large searches. - Test destructive expressions (like
-deleteor-exec rm) by first running the same expression with-print(or no action) to see exactly what would be affected. - Combine
-type fwith-nameto avoid matching directories that happen to share a name pattern. - Use
find ... -print0 | xargs -0 ...when filenames might contain spaces or newlines, to avoid word-splitting bugs.
Best practices
- Prefer
findoverlocatewhen you need guaranteed up-to-date results, such as right after creating or deleting files. - Always dry-run destructive
findexpressions (drop-delete/-exec rmand just look at the match list) before making them destructive. - In scripts, use
-print0/xargs -0or-exec ... +rather than looping over unquotedfindoutput, to handle unusual filenames safely. - Scope searches with a specific starting path and
-maxdepthrather than searching/whenever you know roughly where the files live — it's faster and produces less noise.
Try it yourself
A simulated shell with a sample home directory — experiment freely, nothing leaves your browser. Type help to list supported commands.
Real-world use cases
- Locating and cleaning up old log files or temp files as part of a cron-driven cleanup
script:
find /var/log -name "*.log" -mtime +30 -delete. - Auditing disk usage by hunting down unexpectedly large files:
find / -type f -size +1G. - Bulk-fixing permissions on a deployed codebase:
find . -type f -name "*.sh" -exec chmod +x {} \;. - Finding files modified since a deployment to investigate what changed:
find /app -newer /tmp/deploy-marker.
Common interview questions
- How does find differ from locate? find performs a live filesystem walk every time it runs, so it's always accurate but potentially slow; locate looks up a prebuilt index (updatedb) that's fast but can be stale.
- What's the difference between
-exec CMD {} \;and-exec CMD {} +? The former invokes CMD once per matched file; the latter batches as many matches as possible into each invocation, similar to howxargsbatches arguments, which is much more efficient for commands that support multiple file arguments. - How would you safely delete matched files? Build up the expression without
-deletefirst, review the match list, and only then append-delete— or use-exec rm {} +after confirming the file list looks correct. - How do you avoid issues with filenames containing spaces when piping find output?
Use
find ... -print0combined withxargs -0, which uses null bytes as separators instead of whitespace.
Frequently Asked Questions
What's the difference between find and locate?
find walks the filesystem live at the moment you run it, so results are always current but can be slow on large trees. locate queries a prebuilt index (updatedb) that's usually refreshed once a day, so it's much faster but can miss recently created or deleted files.
How do I find files larger than a certain size?
Use find /path -type f -size +100M to find regular files over 100 megabytes. Use - instead of + to find files smaller than a size.
How do I run a command on every file found?
Append -exec CMD {} \; to run CMD once per match, or -exec CMD {} + to batch matches into fewer invocations (faster for commands like grep or ls).
How do I delete files found by find?
Add -delete at the end of the expression, e.g. find /tmp -name '*.log' -mtime +30 -delete. Always test with -print (or no action) first to confirm the match set before deleting.
Cheat sheet
Download a quick-reference cheat sheet for find.