Skip to main content

Anatomy of the Find Command

find has a strict POSIX grammar. Unlike most CLI tools, argument order is not flexible.

The Structure

find [TRAVERSAL_FLAGS] [PATH...] [EXPRESSION]

Where EXPRESSION = any combination of:

[OPTIONS] [TESTS] [OPERATORS] [ACTIONS]

Visual Breakdown

find -L /var/log -maxdepth 2 -type f -name "*.log" -mtime +30 -delete
│ │ │ │ │ │ │ │
│ traverse │ global opt test 1 test 2 test 3 action
│ flag start
command path

1. Traversal Flags (before path)

FlagBehaviour
-P(default) Never follow symlinks
-LFollow all symlinks
-HFollow symlinks on command line only

2. Starting Path

find . # current directory
find /var/log /etc # multiple start points
find / # entire filesystem

3. Global Options

Place these immediately after the path:

find /var -maxdepth 2 -mindepth 1 -name "*.log"
OptionMeaning
-maxdepth NStop at N levels below start
-mindepth NSkip first N levels
-depthProcess children before parent

4. Tests (Conditions)

These return true/false for each file:

-name "*.log" # filename glob
-type f # regular file
-size +100M # larger than 100 MB
-mtime -7 # modified in last 7 days
-user nginx # owned by nginx
-perm /4000 # SUID bit set

5. Operators

By default, tests are joined with implicit AND:

# Both must be true
find . -type f -name "*.sh"

# OR operator
find . -name "*.sh" -o -name "*.py"

# NOT operator
find . -type f ! -name "*.log"

# Grouping (control precedence)
find . \( -name "*.sh" -o -name "*.py" \) -size +10k

6. Actions

What to do with matched files:

ActionMeaning
-printPrint path (default)
-print0Print with null byte (safe for pipes)
-deleteDelete the file
-exec CMD {} \;Run CMD once per file
-exec CMD {} +Run CMD once for all files
-execdir CMD {} \;Run CMD in file's directory

Expression Order Safety

Wrong order deletes everything
# WRONG: -delete runs BEFORE -name is checked
find /var/log -delete -name "*.log"

# CORRECT: -name filters first, -delete acts after
find /var/log -name "*.log" -delete

The rule: put filters (tests) before actions.