find — recursive filesystem search. Combines filters for name, type, size, time, permissions, and ownership, then runs actions with -exec.
Name & type
Search by name & type
| Command | Description |
|---|---|
| find /etc -name "*.conf" | Files matching glob pattern |
| find /var -iname "*.log" | Case-insensitive match |
| find / -name "passwd" 2>/dev/null | Suppress permission errors |
| find . -type f | Regular files only |
| find . -type d | Directories only |
| find . -type l | Symbolic links only |
| find . -type s | Sockets only |
| find . -maxdepth 2 -name "*.sh" | Limit search depth to 2 levels |
| find . -mindepth 2 -name "*.py" | Skip top level, search from depth 2 |
| find . -not -name "*.log" | Exclude a pattern |
| find . \( -name "*.txt" -o -name "*.md" \) | OR — match either pattern |
| find . -name "*.py" -not -path "*/venv/*" | Exclude a directory subtree |
Size & time
Search by size
| Command | Description |
|---|---|
| find / -size +100M | Larger than 100 MB |
| find / -size -1k | Smaller than 1 KB |
| find / -size +1G -size -10G | Between 1 GB and 10 GB |
| find . -empty | Empty files and directories |
Size units: c bytes · k KB · M MB · G GB. Prefix + = larger than, - = smaller than.
Search by time
| Command | Description |
|---|---|
| find . -mtime -7 | Modified in the last 7 days |
| find . -mtime +30 | Not modified in over 30 days |
| find . -mtime 0 | Modified today (less than 24h ago) |
| find . -mmin -30 | Modified in the last 30 minutes |
| find . -atime -1 | Accessed in the last 24 hours |
| find . -ctime -1 | Inode changed in the last 24 hours |
| find . -newer /etc/passwd | Newer than a reference file |
| find . -newer /etc/passwd -not -newer /tmp/ref | Modified between two reference files |
Time flags: m = modified · a = accessed · c = inode changed. time = days, min = minutes.
Permissions & ownership
Search by permissions
| Command | Description |
|---|---|
| find / -perm 644 | Exact permission 644 |
| find / -perm -644 | At least 644 (all listed bits set) |
| find / -perm /111 | Any execute bit set (u, g, or o) |
| find / -perm -u=x | Owner has execute bit |
| find / -perm -4000 | SUID bit set |
| find / -perm -2000 | SGID bit set |
| find / -perm -1000 | Sticky bit set |
Search by ownership
| Command | Description |
|---|---|
| find / -user alice | Files owned by user alice |
| find / -group staff | Files owned by group staff |
| find / -uid 1001 | Files owned by UID 1001 |
| find / -nouser | No valid owner (orphaned files) |
| find / -nogroup | No valid group |
Actions: -exec & -print0
-exec and actions
| Command | Description |
|---|---|
| find . -name "*.tmp" -exec rm {} \; | Delete each file (one process per file) |
| find . -name "*.tmp" -exec rm {} + | Delete — batch all files into one rm call (faster) |
| find . -type f -exec chmod 644 {} + | Fix file permissions in bulk |
| find . -type d -exec chmod 755 {} + | Fix directory permissions in bulk |
| find . -name "*.sh" -exec chmod +x {} + | Make scripts executable |
| find . -name "*.log" -exec gzip {} \; | Compress each log file |
| find . -name "*.bak" -delete | Delete matching files (built-in, no subprocess) |
| find . -name "*.conf" -exec grep -l "port 22" {} + | Search inside found files |
| find /var/log -name "*.log" -mtime +90 -exec rm {} + | Delete logs older than 90 days |
-print0 & xargs -0 (safe pipes)
| Command | Description |
|---|---|
| find . -name "*.py" -print0 | xargs -0 grep "TODO" | Safe pipe — handles filenames with spaces/newlines |
| find . -print0 | xargs -0 ls -la | List every found file with details |
| find . -name "*.log" -print0 | xargs -0 -P4 gzip | Parallel compression (4 workers) |
| find . -name "*.py" | xargs grep "import" | Plain pipe — breaks on spaces in filenames |
{} is replaced by the filename. \; runs one process per file; + batches all files into one invocation (like xargs). -print0 uses null byte as separator — immune to spaces and special characters.