Every developer knows find . -name "*.txt". Few know that find can replace half your shell scripts.
Beyond Basic Search#
1
2
3
4
5
6
7
8
9
10
11
| # Find by name (case-insensitive)
find . -iname "readme*"
# Find by extension
find . -name "*.py"
# Find by exact name
find . -name "Makefile"
# Find excluding directories
find . -name "*.js" -not -path "./node_modules/*"
|
The -not (or !) operator is your friend for excluding noise.
Filter by Type#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Files only
find . -type f
# Directories only
find . -type d
# Symbolic links
find . -type l
# Empty files
find . -type f -empty
# Empty directories
find . -type d -empty
|
Filter by Time#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Modified in last 24 hours
find . -mtime -1
# Modified more than 7 days ago
find . -mtime +7
# Modified exactly 7 days ago
find . -mtime 7
# Accessed in last hour (minutes)
find . -amin -60
# Changed (metadata) in last day
find . -ctime -1
|
Time units: -mmin (minutes), -mtime (days). The +/- prefix means “more than”/“less than”.
Filter by Size#
1
2
3
4
5
6
7
8
9
10
11
| # Larger than 100MB
find . -size +100M
# Smaller than 1KB
find . -size -1k
# Exactly 0 bytes
find . -size 0
# Between 1MB and 100MB
find . -size +1M -size -100M
|
Units: c (bytes), k (KB), M (MB), G (GB).
Filter by Permissions#
1
2
3
4
5
6
7
8
9
10
11
| # World-writable files (security audit)
find . -perm -002 -type f
# Executable files
find . -perm /u+x -type f
# SUID files (security concern)
find / -perm -4000 -type f 2>/dev/null
# Files with specific permissions
find . -perm 644
|
Filter by Owner#
1
2
3
4
5
6
7
8
| # Files owned by user
find . -user deploy
# Files owned by group
find . -group www-data
# Files with no owner (orphaned)
find . -nouser
|
Combining Filters#
Use -and (default), -or, and parentheses:
1
2
3
4
5
6
7
8
| # Python or JavaScript files
find . \( -name "*.py" -or -name "*.js" \)
# Large, old log files
find /var/log -name "*.log" -size +10M -mtime +30
# Config files modified recently
find /etc -name "*.conf" -type f -mtime -1
|
Taking Action#
-exec: Run Command on Each Result#
1
2
3
4
5
6
7
8
| # Delete old temp files
find /tmp -name "*.tmp" -mtime +7 -exec rm {} \;
# Change permissions
find . -type f -name "*.sh" -exec chmod +x {} \;
# Show file details
find . -name "*.log" -exec ls -lh {} \;
|
The {} is replaced with each filename. \; terminates the command.
-exec with + : Batch Execution#
1
2
3
4
| # Much faster - batches arguments
find . -name "*.txt" -exec grep -l "TODO" {} +
# Compare: \; runs grep once per file, + runs grep once with all files
|
Use + when the command accepts multiple arguments (like grep, rm, chmod).
-delete: Built-in Removal#
1
2
3
4
5
| # Delete empty directories
find . -type d -empty -delete
# Delete old files (CAREFUL!)
find /tmp -mtime +30 -delete
|
-delete implies -depth (processes contents before directory).
-print0 and xargs#
For complex operations or filenames with spaces:
1
2
3
4
5
| # Safe deletion with xargs
find . -name "*.bak" -print0 | xargs -0 rm
# Parallel processing
find . -name "*.jpg" -print0 | xargs -0 -P 4 mogrify -resize 50%
|
Practical Patterns#
Cleanup Old Files#
1
2
3
4
5
| # Delete logs older than 30 days
find /var/log -name "*.log" -mtime +30 -delete
# Archive then delete
find /data -name "*.csv" -mtime +90 -exec gzip {} \; -exec mv {}.gz /archive/ \;
|
Find and Replace in Files#
1
2
3
| # Find files containing pattern, then replace
find . -name "*.py" -exec grep -l "old_function" {} \; | \
xargs sed -i 's/old_function/new_function/g'
|
Disk Usage Investigation#
1
2
3
4
5
| # Top 10 largest files
find . -type f -exec ls -s {} + | sort -n -r | head -10
# Large files by type
find . -name "*.log" -size +100M -exec ls -lh {} \;
|
Security Auditing#
1
2
3
4
5
6
7
8
| # World-writable files
find /var/www -perm -002 -type f
# Files modified in last hour (intrusion detection)
find /var/www -mmin -60 -type f
# SUID/SGID binaries
find / -perm /6000 -type f 2>/dev/null
|
Code Quality#
1
2
3
4
5
6
7
8
| # Find TODOs in codebase
find . -name "*.py" -exec grep -Hn "TODO\|FIXME" {} \;
# Large functions (files over N lines)
find . -name "*.py" -exec awk 'END{if(NR>500)print FILENAME": "NR" lines"}' {} \;
# Files without copyright headers
find . -name "*.py" -exec sh -c 'head -5 "$1" | grep -q "Copyright" || echo "$1"' _ {} \;
|
Sync and Backup#
1
2
3
4
5
| # Find files newer than reference
find . -newer /tmp/last_backup -type f
# Copy structure preserving paths
find . -name "*.conf" -exec cp --parents {} /backup/ \;
|
Limit Depth#
1
2
3
4
5
| # Only current directory
find . -maxdepth 1 -name "*.txt"
# Top two levels
find . -maxdepth 2 -type d
|
Prune Directories#
1
2
3
4
5
| # Skip .git directories entirely
find . -path "./.git" -prune -o -name "*.py" -print
# Skip multiple directories
find . \( -path ./node_modules -o -path ./.git \) -prune -o -type f -print
|
-prune stops descending into matched directories — much faster than -not -path.
Use -quit for First Match#
1
2
| # Stop after finding one
find . -name "config.yaml" -quit
|
Common Mistakes#
Forgetting quotes around patterns:
1
2
3
4
5
| # Bad - shell expands * before find sees it
find . -name *.txt
# Good
find . -name "*.txt"
|
Wrong order with -delete:
1
2
3
4
5
| # DANGEROUS - deletes everything, then filters
find . -delete -name "*.tmp"
# Safe - filter first
find . -name "*.tmp" -delete
|
Inefficient -exec:
1
2
3
4
5
| # Slow - one grep per file
find . -name "*.log" -exec grep "ERROR" {} \;
# Fast - batch
find . -name "*.log" -exec grep "ERROR" {} +
|
Quick Reference#
| Flag | Purpose |
|---|
-name | Match filename pattern |
-iname | Case-insensitive name |
-type f/d/l | Files/directories/links |
-mtime +/-N | Modified N days ago |
-size +/-N | Size threshold |
-perm | Permission match |
-exec cmd {} \; | Run command per file |
-exec cmd {} + | Batch command execution |
-print0 | Null-delimited output |
-delete | Remove matches |
-prune | Skip directory descent |
-maxdepth N | Limit search depth |
find is a complete file-processing language. Learn it well, and you’ll write fewer scripts.
Computing Arts is CLI mastery for working developers. More at computingarts.com.