find
find recursively searches directories for files matching criteria. Master find to locate anything in your filesystem instantly.
Basic Syntax
find [path] [expression]
-
path: Where to search (
.for current,/for root) -
expression: Tests and actions
Finding by Name
Exact Match
find . -name "config.yaml"
Glob Patterns
# All .adoc files
find . -name "*.adoc"
# Single character wildcard
find . -name "file?.txt"
# Character class
find . -name "file[0-9].txt"
Case-Insensitive
find . -iname "readme*"
Path Matching
# Match path pattern
find . -path "*/modules/ROOT/*"
# Exclude paths
find . -path "*/node_modules" -prune -o -name "*.js" -print
Finding by Type
| Type | Meaning |
|---|---|
|
Regular file |
|
Directory |
|
Symbolic link |
|
Block device |
|
Character device |
|
Named pipe (FIFO) |
|
Socket |
# Files only
find . -type f -name "*.log"
# Directories only
find . -type d -name "backup*"
# Symlinks only
find /usr/bin -type l
Finding by Time
Modification Time (-mtime)
# Modified in last 24 hours
find . -mtime -1
# Modified exactly 7 days ago
find . -mtime 7
# Modified more than 30 days ago
find . -mtime +30
Access Time (-atime)
# Accessed in last hour
find . -amin -60
# Not accessed in 90 days
find . -atime +90
Minutes vs Days
| Days | Minutes |
|---|---|
-mtime |
-mmin |
-atime |
-amin |
-ctime |
-cmin |
Newer Than File
# Files newer than reference file
find . -newer reference.txt
# Files newer than timestamp
find . -newermt "2026-03-01"
# Files between dates
find . -newermt "2026-03-01" ! -newermt "2026-03-15"
Finding by Size
# Exactly 100 bytes
find . -size 100c
# Files larger than 10MB
find . -size +10M
# Files smaller than 1KB
find . -size -1k
# Empty files
find . -size 0
# Or use -empty
find . -empty
Size Units
| Unit | Meaning |
|---|---|
c |
bytes |
k |
kilobytes (1024 bytes) |
M |
megabytes |
G |
gigabytes |
Finding by Permissions
# Exact permissions (octal)
find . -perm 644
# At least these permissions
find . -perm -644
# Any of these permissions
find . -perm /644
# World-writable files
find . -perm -002
# SUID files
find . -perm -4000
# SGID files
find . -perm -2000
Finding by Ownership
# By user name
find . -user jdoe
# By user ID
find . -uid 1000
# By group name
find . -group wheel
# By group ID
find . -gid 1000
# No owner (orphaned)
find . -nouser
# No group
find . -nogroup
Combining Tests
AND (implicit)
# Both conditions must match
find . -type f -name "*.log"
OR (-o)
# Either condition
find . -name "*.jpg" -o -name "*.png"
# With grouping
find . \( -name "*.jpg" -o -name "*.png" \) -type f
NOT (!)
# Exclude pattern
find . -type f ! -name "*.bak"
# Exclude directory
find . -type d ! -name "temp"
Complex Logic
# Files that are large AND old
find . -type f -size +10M -mtime +30
# Files that are images OR videos
find . -type f \( -name "*.jpg" -o -name "*.mp4" \)
# Config files NOT in backup directories
find . -name "*.conf" ! -path "*/backup/*"
Actions
Print (default)
find . -name "*.txt"
find . -name "*.txt" -print
Print with Null
# For xargs -0 (handles spaces in names)
find . -name "*.txt" -print0
Print Formatted
# Custom format
find . -name "*.log" -printf "%p %s %T+\n"
Format specifiers:
| Spec | Meaning |
|---|---|
%p |
Filename with path |
%f |
Filename only |
%s |
Size in bytes |
%T+ |
Modification time |
%u |
Owner name |
%m |
Permissions (octal) |
Execute Command (-exec)
# For each file, run command
find . -name "*.tmp" -exec rm {} \;
# Combine into single command (efficient)
find . -name "*.tmp" -exec rm {} +
# Prompt before each
find . -name "*.tmp" -ok rm {} \;
-
{}= placeholder for filename -
\;= end of command (run once per file) -
+= end of command (batch files together)
Execute with Shell
# When you need shell features
find . -name "*.log" -exec sh -c 'gzip "$1"' _ {} \;
Delete (-delete)
# Delete matching files
find . -name "*.tmp" -delete
# WARNING: -delete is IMMEDIATE, no confirmation
# Always test with -print first!
find . -name "*.tmp" -print
Pruning (Excluding Directories)
# Skip .git directories
find . -name ".git" -prune -o -name "*.txt" -print
# Skip multiple directories
find . \( -name "node_modules" -o -name ".git" \) -prune -o -type f -print
Depth Control
# Maximum depth
find . -maxdepth 2 -name "*.txt"
# Minimum depth
find . -mindepth 2 -name "*.txt"
# Exactly 2 levels deep
find . -mindepth 2 -maxdepth 2 -type f
Follow Symlinks
# Follow symbolic links
find -L . -name "*.conf"
# Don't follow (default)
find -P . -name "*.conf"
Performance Tips
Use xargs Instead of -exec \;
# Slow (one rm per file)
find . -name "*.tmp" -exec rm {} \;
# Fast (batch rm)
find . -name "*.tmp" -exec rm {} +
# Fastest (xargs with null)
find . -name "*.tmp" -print0 | xargs -0 rm
Prune Early
# Put -prune first to skip directories early
find . -name "node_modules" -prune -o -type f -name "*.js" -print
Use -quit for First Match
# Stop after first match
find . -name "config.yaml" -quit
Infrastructure Patterns
Find Old Logs
find /var/log -name "*.log" -mtime +30 -type f
Find Large Files
find / -type f -size +100M 2>/dev/null | head -20
Find Recently Changed Config
find /etc -name "*.conf" -mtime -1 -type f
Find World-Writable
find / -type f -perm -002 2>/dev/null
Find Broken Symlinks
find . -xtype l
Find Empty Directories
find . -type d -empty
Find Duplicate Filenames
find . -type f -name "*.conf" | xargs -I{} basename {} | sort | uniq -d
Find and Process ISE Backup Files
find /backup -name "ise-*.tar.gpg" -mtime +30 -exec mv {} /archive/ \;
Practice Exercises
Exercise 1: Find AsciiDoc Files
# Find all .adoc files in domus-captures
find ~/atelier/_bibliotheca/domus-captures -name "*.adoc" -type f | wc -l
Exercise 2: Find Recent Worklogs
# Worklogs modified in last 7 days
find . -path "*/WRKLOG-*.adoc" -mtime -7
Exercise 3: Find Large Diagrams
# SVG files larger than 100KB
find . -name "*.svg" -size +100k
Exercise 4: Clean Temp Files
# Find and preview
find . -name "*.tmp" -o -name "*~" -type f
# Then delete
find . \( -name "*.tmp" -o -name "*~" \) -type f -delete
Key Takeaways
-
-namefor filename,-pathfor full path -
-type ffor files,-type dfor directories -
-mtime -1= last 24 hours -
-exec {} +for batching (fast) -
-print0 | xargs -0for safety -
-pruneto skip directories -
Always test with
-printbefore-delete
Next Module
grep - Pattern matching in files.