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

-type f

Regular file

-type d

Directory

-type l

Symbolic link

-type b

Block device

-type c

Character device

-type p

Named pipe (FIFO)

-type s

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

Change Time (-ctime)

Metadata change (permissions, ownership):

find . -ctime -1

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 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 . -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

  1. -name for filename, -path for full path

  2. -type f for files, -type d for directories

  3. -mtime -1 = last 24 hours

  4. -exec {} + for batching (fast)

  5. -print0 | xargs -0 for safety

  6. -prune to skip directories

  7. Always test with -print before -delete

Next Module

grep - Pattern matching in files.