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

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 f for files only and 2>/dev/null to suppress errors.

Back to the top, you overachiever.