find — quick reference
Starting points and depth
Control where the walk begins and how deep it recurses — useful on large trees like /var or /home.
| When to use | Command |
|---|---|
| Search from the current directory (default when no path is given) | find . |
| Search from a specific directory | find /var/log |
| Limit recursion to N levels below the start path | find . -maxdepth 2 |
| Skip the start directory itself; search from level N onward | find . -mindepth 2 |
| Stay on the same filesystem (do not cross mount points) | find / -xdev -name "lost+found" |
Name and path matching
Match basenames or full paths. Quote wildcard patterns so the shell does not expand them first.
| When to use | Command |
|---|---|
| Exact filename (case-sensitive) | find . -name "readme.txt" |
| Filename match ignoring case | find . -iname "readme.txt" |
| Files whose names match a shell-style pattern | find . -name "*.log" |
| Match the full path string, not just the basename | find . -path "./logs/*" |
| Skip a subdirectory entirely during the walk | find . -path "./node_modules" -prune -o -print |
File type, size, and emptiness
Filter by inode type, disk usage, or whether a file or directory has no content.
| When to use | Command |
|---|---|
| Regular files only | find . -type f |
| Directories only | find . -type d |
| Symbolic links only | find . -type l |
| Files larger than 100 MB | find . -type f -size +100M |
| Files smaller than 10 MB | find . -type f -size -10M |
| Zero-byte regular files | find . -type f -empty |
| Empty directories | find . -type d -empty |
Time-based tests
-mtime counts whole days since last content change; -mmin uses minutes for finer windows.
| When to use | Command |
|---|---|
| Modified within the last 7 days | find . -mtime -7 |
| Modified more than 30 days ago | find . -mtime +30 |
| Accessed within the last 24 hours | find . -atime -1 |
| Metadata changed within the last 3 days | find . -ctime -3 |
| Modified within the last 60 minutes | find . -mmin -60 |
Ownership and permissions
Locate files by owner, group, or permission bits — common in security audits and cleanup scripts.
| When to use | Command |
|---|---|
| Files owned by a specific user | find . -user "$(whoami)" |
| Files belonging to a specific group | find . -group www-data |
| Exact permission mode (octal) | find . -perm 755 |
| At least these permission bits set (any of 644) | find . -perm -644 |
| Files with the setuid bit set | find /usr/bin -perm -4000 2>/dev/null |
| Readable by the current user | find . -readable |
Actions on matches
Print paths by default; add actions to run commands, list details, or delete — preview matches before destructive actions.
| When to use | Command |
|---|---|
| Print matched paths (default action) | find . -name "*.log" -print |
| Run a command once per match | find . -name "*.log" -exec ls -lh {} \; |
Run a command with many files batched ({} +) |
find . -name "*.log" -exec wc -l {} + |
| Delete matched files (irreversible — preview first) | find . -name "*.tmp" -delete |
Detailed ls-style listing of matches |
find . -name "*.conf" -ls |
| Stop searching after the first match | find /etc -name "hosts" -quit |
Help and version
| When to use | Command |
|---|---|
| Show brief usage | find --help |
| Show findutils version | find --version |
find — command syntax
Synopsis from find --help on Ubuntu 25.04 (GNU findutils 4.10.0):
find [-H] [-L] [-P] [-Olevel] [-D debugopts] [path...] [expression]
Default path is the current directory; default expression is -print.
Expression may consist of: operators, options, tests, and actions.If you omit the path, find starts in the current working directory. Tests and actions are evaluated in order; combine them with -and (implicit), -or, or -not. Filenames that start with a dash need care when passed to other tools — see dashed filenames in Linux.
find — command examples
Essential List everything under a directory
The simplest use is a recursive listing starting from . or an absolute path. Every file and directory under the start point is printed.
Run the command (lab tree under /tmp/find-lab-test):
find /tmp/find-lab-testSample output:
/tmp/find-lab-test
/tmp/find-lab-test/bigfile.dat
/tmp/find-lab-test/link.txt
/tmp/find-lab-test/readme.txt
/tmp/find-lab-test/node_modules
/tmp/find-lab-test/scripts
/tmp/find-lab-test/scripts/run.sh
/tmp/find-lab-test/logs
/tmp/find-lab-test/logs/old.log
/tmp/find-lab-test/logs/app.logUse -type f or -type d when you only want files or directories — the quick-reference tables above list those filters.
Essential Find files by name or extension
Use -name with a quoted pattern to match basenames. Wildcards * and ? are interpreted by find, not expanded by the shell.
Run the command:
find /tmp/find-lab-test -name "*.log"Sample output:
/tmp/find-lab-test/logs/old.log
/tmp/find-lab-test/logs/app.logFor a case-insensitive match, swap -name for -iname. Always quote patterns that contain * so the shell does not expand them in the current directory first.
Essential Regular files only — skip directories
-type f limits results to regular files. Pair it with other tests to avoid matching directory names.
Run the command:
find /tmp/find-lab-test -type fSample output:
/tmp/find-lab-test/bigfile.dat
/tmp/find-lab-test/readme.txt
/tmp/find-lab-test/scripts/run.sh
/tmp/find-lab-test/logs/old.log
/tmp/find-lab-test/logs/app.logSymlinks are not listed unless you use -type l or follow links with -L.
Common Find files larger than a size threshold
-size accepts c, k, M, G, and related suffixes. A leading + means strictly greater; - means strictly less.
Run the command:
find /tmp/find-lab-test -type f -size +1MSample output:
/tmp/find-lab-test/bigfile.datCombine two -size tests to bracket a range, for example -size +50M -size -200M for files between 50 MB and 200 MB.
Common Files modified recently or long ago
-mtime -N matches files changed within the last N days; -mtime +N matches files older than N days.
Run the command:
find /tmp/find-lab-test -mtime +30Sample output:
/tmp/find-lab-test/logs/old.logUse -mtime -7 for recent changes or -mmin -60 when you need a window measured in minutes instead of days.
Common Limit how deep find recurses
On large trees, -maxdepth keeps the walk shallow and faster. Depth 1 is the start directory itself; depth 2 includes its immediate children.
Run the command:
find /tmp/find-lab-test -maxdepth 2 -type fSample output:
/tmp/find-lab-test/bigfile.dat
/tmp/find-lab-test/readme.txt
/tmp/find-lab-test/scripts/run.sh
/tmp/find-lab-test/logs/old.log
/tmp/find-lab-test/logs/app.logAdd -name "*.conf" or other tests after the depth limit to narrow results further.
Common Run a command on each match with -exec
-exec runs an external command for every match. {} is replaced by the path; \; ends the action for one file at a time.
Run the command:
find /tmp/find-lab-test -name "*.log" -exec grep -H "error" {} \;Sample output:
/tmp/find-lab-test/logs/app.log:error: disk fullFor many files, -exec cmd {} + batches arguments into fewer process runs — often faster than \;.
Advanced Skip directories such as node_modules
-prune prevents descending into a path. Combine it with -o (OR) so other branches still print.
Run the command:
find /tmp/find-lab-test \( -path "*/node_modules" -o -path "*/.git" \) -prune -o -type f -printSample output (note node_modules and .git are absent):
/tmp/find-lab-test/bigfile.dat
/tmp/find-lab-test/readme.txt
/tmp/find-lab-test/scripts/run.sh
/tmp/find-lab-test/logs/old.log
/tmp/find-lab-test/logs/app.logAdjust the -path patterns to match directories you want to skip in your project tree.
Advanced Preview matches, then delete with -delete
-delete removes matched files immediately. Always run the same expression without -delete first to confirm the list.
Preview:
find /tmp/find-lab-test -name "*.tmp"Sample output:
/tmp/find-lab-test/empty.tmpDelete after confirming:
find /tmp/find-lab-test -name "*.tmp" -delete
find /tmp/find-lab-test -name "*.tmp"Second command sample output (empty — file removed):
For production log rotation, combine age and name tests, for example find /var/log -name "*.log" -mtime +30 -delete, only after a dry run without -delete.
Advanced Permission denied on system paths
Searching / or /root as a normal user often prints Permission denied for directories you cannot read. The search continues, but stderr is noisy.
Run the command:
find /root -maxdepth 1 2>&1 | head -3Sample output:
/root
/root/golinuxcloud-static
/root/.gnupg
find: '/root/.gnupg': Permission deniedRedirect stderr to hide denials when you only care about readable paths:
find /root -maxdepth 1 2>/dev/nullUse sudo find … when you genuinely need to inspect protected directories — not for everyday file searches.
find — when to use / when not
| Use find when | Use something else when |
|---|---|
|
find vs locate
| find | locate | |
|---|---|---|
| Data source | Walks the filesystem in real time | Queries a pre-built database (updatedb) |
| Accuracy | Always current | Can miss files until the next database update |
| Speed on large disks | Slower — reads directories as it goes | Very fast for simple name lookups |
| Filters | Name, type, size, time, owner, permissions, actions | Mainly path/name patterns |
| Best for | Audits, cleanup scripts, complex criteria | Quick “where is this file?” on a familiar host |
See the locate command for database setup and updatedb.
Related commands
Nearby tools for search, filtering, and batch processing.
| Command | One line |
|---|---|
| find | Walk a tree and match by metadata (this page) |
xargs |
Build command lines from stdin path lists |
ls |
List one directory level |
Browse the full index in our Linux commands reference.
find — interview corner
What does the find command do in Linux?
find (from GNU findutils) recursively walks directories starting from one or more paths. For each file system object it evaluates tests — name, type, size, modification time, owner, permissions — and optionally runs actions such as -print, -exec, or -delete.
Unlike locate, find reads the live directory structure, so results reflect the disk right now. That makes it the standard choice for log cleanup, security checks (SUID files), and automation.
A strong answer is:
"find walks a directory tree in real time, filters by tests like -name, -type, -size, and -mtime, and can print paths or run actions such as -exec and -delete. I use it when criteria are more than a simple filename or when the result must be current."
What does find -mtime -7 mean?
-mtime compares the file's last content modification time to now, in 24-hour day units.
-mtime -7— modified less than 7 days ago (recent files)-mtime +7— modified more than 7 days ago (older files)-mtime 7— modified exactly around 7 days ago (rare in practice)
The minus sign means "less than N days"; the plus sign means "greater than N days". For minute-level windows use -mmin instead.
A strong answer is:
"find -mtime -7 matches files changed within the last seven days. Minus means newer than N days; plus means older than N days. For minutes I'd use -mmin."
When do you use find -exec versus find | xargs?
Both run a command on matched paths, but the wiring differs.
-exec cmd {} \; — one process per file; safe with odd filenames if {} is used correctly.
-exec cmd {} + — batches many paths into one command (like xargs).
find … -print0 | xargs -0 cmd — hands paths to xargs; use -print0 and xargs -0 when names may contain spaces or newlines.
Preview with find … alone before adding -delete or rm.
A strong answer is:
"I use -exec {} + for batching inside find, or find -print0 | xargs -0 when piping to another tool. For destructive actions I always preview the find expression first."
What is the difference between find and locate?
| find | locate | |
|---|---|---|
| Mechanism | Directory walk | Database lookup |
| Freshness | Real time | Depends on updatedb schedule |
| Filters | Rich (size, time, perm, …) | Mostly path/name |
| Cost | Higher I/O on big trees | Low for simple queries |
Use locate for a quick "is this file somewhere on the system?" Use find when age, size, or permissions matter, or when you must act on matches.
A strong answer is:
"locate is fast but can be stale; find is slower but live and supports rich filters and -exec. I pick find for cleanup scripts and audits, locate for quick name lookups."
Why must wildcard patterns be quoted in find -name?
The shell expands unquoted * before find runs. If you type:
find . -name *.logand the current directory has app.log, the shell may turn that into find . -name app.log — not what you intended.
Quoting keeps the pattern intact for find:
find . -name "*.log"Same rule applies to -path and -wholename patterns.
A strong answer is:
"I quote patterns like "*.log" so the shell doesn't glob them first — find should interpret the wildcards, not bash."
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Permission denied lines on stderr |
Normal user reading protected dirs | 2>/dev/null, narrow the path, or sudo find … when appropriate |
| No matches but the file exists | Wrong path, -maxdepth too shallow, or typo in -name |
Run find START -name 'exactname'; drop depth limits temporarily |
-delete removed too much |
Expression matched more than expected | Preview without -delete; add -type f and tighter -name / -mtime tests |
| Shell glob expanded the pattern | Unquoted * in -name |
Quote the pattern: -name "*.log" |
-exec runs once per file slowly |
Using \; on huge sets |
Switch to -exec cmd {} + or find … -print0 | xargs -0 |
| Symlink surprises | Default -P does not follow symlinks into dirs |
Use -L only when following links is intentional |
