find system
your GUI search bar is lying to you about what's on your disk.
The find man page is 1,200 lines long. You need about five patterns and you’ll locate any file on any system in seconds.
You lost a file. Or you needed to find all the log files. Or you wanted to know which config files were modified recently. So you opened your file manager, clicked the search bar, typed a name, and waited. And waited. Your operating system’s search indexer — which has been running in the background eating CPU and disk I/O since boot — either found what you wanted or didn’t, with no explanation as to why.
On Windows, the search is particularly entertaining. You type a filename. Windows Search thinks about it. It shows you “results from the web” because apparently you wanted to search Bing for a file on your own computer. Then it shows three results from 2019, none of which are what you’re looking for, because the search index is either corrupt, incomplete, or indexing a different drive.
find doesn’t use an index. It reads the filesystem directly. It finds everything. It finds it now. And it tells you exactly where it is.
Unless you’re running Windows then wtf none of this applies to you. But hey, come to the dark side, go install WSL2 and you can follow along. We’ll wait. Impatiently.
If you’re lazy like me (all sysadmins are!) then click here for the find cheat sheet.
Find a file by name
find / -name "config.yml"
Searches the entire filesystem for a file named exactly config.yml. The / means “start from the root.” Replace with any directory to narrow the search:
find /etc -name "nginx.conf"
find /home -name "*.log"
Case-insensitive search
find / -iname "readme*"
-iname ignores case. Finds README.md, readme.txt, ReadMe.doc — whatever capitalization someone felt creative about.
Find by file type
find /home -type f -name "*.py"
-type f means files only. -type d means directories only.
find /var -type d -name "log*"
Find all directories starting with “log” under /var. No files, just directories.
| Type | What it matches |
|---|---|
f |
Regular files |
d |
Directories |
l |
Symbolic links |
Find by size
find /home -type f -size +100M
Files over 100MB. For when you’re out of disk space and need to find what’s eating it. Pairs perfectly with df and du.
find /var/log -type f -size +1G
Log files over 1GB. Someone forgot to set up log rotation.
find /tmp -type f -size -1k
Files under 1KB. The + means “larger than,” - means “smaller than,” no prefix means exactly.
Find by modification time
find /etc -mtime -7
Files modified in the last 7 days. -mtime -7 means “less than 7 days ago.” For answering “what changed recently?” after something broke.
find /var/log -mtime +30
Files not modified in over 30 days. Old logs. Old temp files. Candidates for cleanup.
find /home -mmin -60
Modified in the last 60 minutes. -mmin uses minutes instead of days. For when you need finer granularity.
Find by permissions
find / -perm 777
Files with full read/write/execute for everyone. Security red flag. If you find any outside of /tmp, investigate.
find /home -perm -u+s
Files with the SUID bit set. These run as the file owner regardless of who executes them. A common attack vector. Know what’s on your system.
Find and do something with the results
This is where find becomes a power tool.
Delete matching files
find /tmp -type f -name "*.tmp" -mtime +7 -delete
Temp files older than a week. Gone. The -delete flag removes them without asking. Be very sure about your filters before using this.
Execute a command on each result
find /var/log -name "*.log" -size +100M -exec ls -lh {} \;
Finds large log files and runs ls -lh on each one. The {} is replaced with each filename. The \; terminates the command.
find . -name "*.py" -exec grep -l "TODO" {} \;
Find all Python files containing “TODO.” find locates the files, grep -l checks the contents.
More efficient: use + instead of ;
find . -name "*.js" -exec wc -l {} +
The + passes multiple files to the command at once instead of running it separately for each file. Faster for large result sets.
Pipe to xargs
find . -name "*.log" | xargs rm
Another way to act on results. xargs takes the list from find and passes it as arguments to rm. For filenames with spaces, use:
find . -name "*.log" -print0 | xargs -0 rm
-print0 and -0 use null separators instead of newlines, handling filenames with spaces and special characters safely.
Combine conditions
AND (default)
find /home -name "*.log" -size +10M
Files matching both conditions — name ends in .log AND size over 10MB.
OR
find /home \( -name "*.log" -o -name "*.tmp" \)
Log files or temp files. The parentheses (escaped with backslashes) group the OR condition.
NOT
find /home -not -name "*.git"
Everything except .git files. Also written as ! -name "*.git".
Suppress permission errors
find / -name "config.yml" 2>/dev/null
When searching from root, you’ll hit directories you can’t read. The “Permission denied” errors clutter your output. 2>/dev/null sends them to the void.
The flags that actually matter
| Flag | What it does |
|---|---|
-name PATTERN |
Match by filename (case-sensitive, supports wildcards). |
-iname PATTERN |
Match by filename, case-insensitive. |
-type f/d/l |
Match by type (file/directory/symlink). |
-size +/-N |
Match by size (k, M, G). |
-mtime +/-N |
Modified more/less than N days ago. |
-mmin +/-N |
Modified more/less than N minutes ago. |
-perm MODE |
Match by permissions. |
-user NAME |
Match by owner. |
-exec CMD {} \; |
Execute a command on each result. |
-delete |
Delete matching files. |
-maxdepth N |
Don’t descend more than N levels deep. |
-print0 |
Null-separated output (safe for xargs -0). |
“But the search bar—”
Here we go.
“Spotlight finds everything on my Mac.” Spotlight uses a background indexing service that consumes CPU and battery to pre-index your filesystem. When it works, it’s fast. When the index corrupts — and it does — you rebuild it and wait thirty minutes. find doesn’t index anything. It searches. Right now. Every time.
“Windows Search has Cortana integration.” Windows Search has been renamed, redesigned, and broken in every major Windows release since Vista. It currently searches Bing, your email, and your files simultaneously — because when you’re looking for database_backup.sql, you definitely also want web results for “database backup.” find /home -name "database_backup.sql" finds the file. Just the file.
“I use locate because it’s faster.” locate uses a pre-built database (updatedb runs periodically). It’s fast because it searches the database, not the filesystem. But if a file was created after the last updatedb run, locate won’t find it. find always finds it because it reads the disk directly. Use locate for speed, find for accuracy, and know the difference.
“Everything (voidtools) is amazing on Windows.” Everything is genuinely fast and impressive. It’s also Windows-only, 1.5MB, and a GUI application. If you’re on Linux, you have find. If you’re on a server, you have find. If you’re in an SSH session, you have find. One tool. Every platform. No install.
find cheat sheet
You made it. Or you skipped straight here. Either way, no judgment. Copy and paste these. Pin them. Tattoo them on your forearm. Whatever works.
| What you’re doing | Command |
|---|---|
| Find by name | find /path -name "*.conf" |
| Case-insensitive | find /path -iname "readme*" |
| Files only | find /path -type f -name "*.py" |
| Directories only | find /path -type d -name "log*" |
| Files over 100MB | find /path -type f -size +100M |
| Modified in last 7 days | find /path -mtime -7 |
| Modified in last hour | find /path -mmin -60 |
| Not modified in 30 days | find /path -mtime +30 |
| Execute on results | find /path -name "*.log" -exec ls -lh {} \; |
| Delete matching files | find /tmp -name "*.tmp" -mtime +7 -delete |
| Suppress errors | find / -name "file" 2>/dev/null |
| Safe xargs | find . -name "*.log" -print0 | xargs -0 rm |
The one command:
find /path -name "pattern"— everything else is refinement. Add-type ffor files only and2>/dev/nullto suppress errors.