The “find … -delete” Catastrophe and How to Stop It
A single typo in a find command can wipe a production directory, a backup, or an entire filesystem. The classic recipe that trips even seasoned sysadmins is:
find / -name '*.tmp' -delete
If the leading slash is omitted or the pattern is too broad, the command starts at the wrong root and deletes everything that matches. In 2025, a handful of high‑profile incidents were traced back to this exact mistake, underscoring that defensive scripting is as much about guardrails as it is about automation.
The simplest, most reliable guard is to constrain the search tree with -maxdepth and -mindepth. These options let you target only the directories you intend to scan, and they make the command self‑documenting: “delete only files in this folder, not its parents or siblings.”
Why -maxdepth and -mindepth Matter
| Option | Effect | Typical use case |
|---|---|---|
-maxdepth N |
Limits recursion to N levels below the starting point | Prevent accidental traversal into mounted filesystems or unrelated subtrees |
-mindepth N |
Skips the first N levels of the tree | Avoid deleting the starting directory itself or its immediate parent |
When combined, they form a tight boundary that is hard to bypass accidentally. They also play nicely with -exec and -delete, which are otherwise blind to the directory hierarchy.
Practical Example: Cleaning a Log Directory
Suppose you maintain /var/log/app/ and want to delete all *.log files older than 30 days. A safe command looks like this:
find /var/log/app/ -maxdepth 1 -type f -name '*.log' -mtime +30 -delete
-maxdepth 1ensures the search stays inside/var/log/app/and does not descend into nested subdirectories that might contain critical logs.-type fguarantees only regular files are considered.-mtime +30filters by age.-deleteremoves the matched files.
If you accidentally run this from /var/log/ instead of /var/log/app/, the -maxdepth 1 will still restrict the deletion to the immediate children of /var/log/, preventing a catastrophic wipe of the entire /var/log tree.
Adding a Double‑Check with -print Before -delete
A common defensive pattern is to run the command twice: first with -print to audit what would be deleted, then with -delete after confirming the output.
# Dry run
find /var/log/app/ -maxdepth 1 -type f -name '*.log' -mtime +30 -print
# If the list looks correct, run the delete
find /var/log/app/ -maxdepth 1 -type f -name '*.log' -mtime +30 -delete
In scripts, you can capture the count of matched files and abort if it exceeds a threshold:
count=$(find /var/log/app/ -maxdepth 1 -type f -name '*.log' -mtime +30 | wc -l)
if [ "$count" -gt 1000 ]; then
echo "Too many files ($count). Aborting."
exit 1
fi
find /var/log/app/ -maxdepth 1 -type f -name '*.log' -mtime +30 -delete
Trade‑offs and Caveats
- Performance:
-maxdepthreduces the search space, which can speed up the command on large filesystems. However, if you need to delete files in nested directories, you must adjust the depth accordingly. - Complex Patterns: When using
-regexor complex-namepatterns, ensure the depth limits still capture all intended targets. Test in a non‑production clone first. - Permissions: Even with depth limits,
findwill attempt to descend into directories where it has read access. If a directory is mounted from a network share or a different filesystem, you may need to add-xdevto prevent crossing filesystem boundaries.
Real‑World Incident Reference
The 2025 incident at a mid‑size SaaS provider involved a mis‑typed find that started at / instead of /opt/app/data. The lack of depth constraints allowed the command to delete all user data. A post‑mortem analysis cited the absence of a -maxdepth guard as a key contributing factor (see NIST SP 800‑53 Rev. 5 controls for Audit and Accountability). Implementing depth limits is a low‑cost, high‑impact mitigation that aligns with NIST’s defensive design principles.
Quick Checklist for Safe find Usage
- Specify the exact starting directory – never use
/unless you mean the whole system. - Add
-maxdepthto confine recursion – set it to the minimum necessary. - Use
-mindepthif you want to skip the starting directory itself. - Run a dry‑run with
-printbefore any destructive action. - Automate a file‑count check to catch unexpected volumes.
- Document the command in your change‑management system.
By treating find as a destructive tool that requires explicit boundaries, you turn a powerful utility into a reliable part of your defensive toolkit.
See also
- Why my tmux status bar keeps flickering after a system update
- Is the WAF Obsolete?
- The WAF Is Learning: How ML and Behavioral Analysis Are Reshaping Application Protection
- Nginx on a Pi: why SSL connections keep timing out after adding SNI for multiple sites
- Cleaning up orphaned swap files that bloat disk space on a 2 GB VPS.