I still remember the first time I needed to find a config file buried somewhere in my Linux system. I was three coffees deep at 2 AM, frantically typing ls commands through every directory like some kind of terminal archaeologist. Then a colleague showed me the find command, and honestly, it felt like discovering fire.
The Linux find command is one of those tools that separates casual users from power users. It’s not just about locating files—it’s about surgical precision in navigating your entire filesystem. Whether you’re hunting down log files eating up disk space, searching for files modified in the last hour, or batch-processing hundreds of files at once, find is your Swiss Army knife.
Let me walk you through everything I’ve learned about this incredibly powerful command, from basic searches to advanced tricks that’ll save you hours of manual work.
What is the Linux Find Command?
The find command searches for files and directories in a directory hierarchy based on criteria you specify. Unlike simple searches that just match filenames, find lets you search by name patterns, file types, permissions, sizes, modification times, and much more—then perform actions on what it finds.
The basic syntax looks like this:
find [path] [options] [expression]
Simple enough, right? But the real magic is in how you combine these elements.
Basic Find Command Examples
Finding Files by Name
The most common use case is finding files by name. Here’s how I search for a specific file:
find /home/alice -name "config.txt"
This searches my entire home directory for a file named exactly “config.txt”. But here’s the thing—find is case-sensitive by default. I learned this the hard way when I couldn’t find “README.md” because I was searching for “readme.md”.
For case-insensitive searches, use -iname:
find /var/www -iname "index.html"
Using Wildcards and Patterns
Wildcards make find exponentially more useful. Here are some patterns I use constantly:
# Find all Python files find . -name "*.py" # Find files starting with "test" find /home/alice/projects -name "test*" # Find files with specific extensions find . -name "*.log" -o -name "*.tmp"
Pro tip: Always put wildcards in quotes! Without quotes, your shell will expand them before find even sees them, and you’ll get weird results.
Finding Directories vs. Files
You can limit your search to just directories or just files using the -type option:
# Find only directories find /var -type d -name "log*" # Find only regular files find /home -type f -name "*.conf" # Find symbolic links find /usr/bin -type l
This is super handy when you’re troubleshooting broken symlinks or organizing directory structures.
Searching by File Properties
Finding Files by Size
Disk space issues? The -size option is a lifesaver. I use this all the time to hunt down large files:
# Files larger than 100MB find /var/log -type f -size +100M # Files smaller than 1KB find . -type f -size -1k # Files exactly 512 bytes find . -type f -size 512c
Size units: c (bytes), k (kilobytes), M (megabytes), G (gigabytes).
Last week, my server’s disk was mysteriously full. One find / -type f -size +1G command later, I found a forgotten 50GB database dump in /tmp. Crisis averted.
Finding Files by Modification Time
Time-based searches are crucial for debugging and system administration:
# Files modified in the last 7 days find /home/alice -type f -mtime -7 # Files modified more than 30 days ago find /var/backups -type f -mtime +30 # Files modified in the last 24 hours find . -type f -mtime 0 # Files modified in the last 60 minutes find /var/log -type f -mmin -60
The -mtime flag uses days, while -mmin uses minutes. There’s also -atime (access time) and -ctime (change time), but I find -mtime covers 90% of my use cases.
If you’re working with services and need to check when configuration files were last updated, you might want to read about systemctl restart vs reload to understand how config changes affect running services.
Finding Files by Permissions
Security audits often involve finding files with specific permissions:
# Find files with 777 permissions (dangerous!) find /var/www -type f -perm 0777 # Find files owned by a specific user find /home -user alice # Find files with SUID bit set find / -type f -perm -4000
Speaking of permissions, if you’re not completely comfortable with chmod yet, check out my guide on the Linux chmod command to understand how permission modes work.
Advanced Find Techniques
Combining Multiple Conditions
Here’s where find gets really powerful. You can combine conditions with logical operators:
# AND condition (both must be true) find . -name "*.log" -size +10M # OR condition (either can be true) find . -name "*.log" -o -name "*.tmp" # NOT condition (invert the match) find . -type f ! -name "*.txt" # Complex combinations find /var/log -type f \( -name "*.log" -o -name "*.gz" \) -size +50M
That last example finds all log files (compressed or not) larger than 50MB. The parentheses group conditions—just remember to escape them with backslashes!
Executing Commands on Found Files
This is where find becomes genuinely magical. You can execute commands on every file it finds:
# Delete all .tmp files
find . -name "*.tmp" -exec rm {} \;
# Change permissions on all shell scripts
find . -name "*.sh" -exec chmod +x {} \;
# Copy all config files to a backup directory
find /etc -name "*.conf" -exec cp {} /backup/ \;
# Show detailed info for each file
find . -name "*.py" -exec ls -lh {} \;
The {} is a placeholder for each file found, and \; marks the end of the command.
Warning: Be extremely careful with -exec rm. I once accidentally nuked an entire project directory because I got my path wrong. Always test with -exec ls first!
Using -exec with Confirmation
For safer operations, use -ok instead of -exec. It’ll prompt you before each action:
find . -name "*.bak" -ok rm {} \;
This asks for confirmation before deleting each .bak file. Much safer when you’re not 100% sure.
More Efficient Batch Processing with xargs
For better performance with large numbers of files, pipe to xargs:
# Faster than -exec for many files find . -name "*.log" -print0 | xargs -0 rm # Process files in parallel find . -name "*.jpg" -print0 | xargs -0 -P 4 jpegoptim
The -print0 and -0 options handle filenames with spaces correctly.
Practical Real-World Examples
Let me share some scenarios I’ve actually encountered and how find saved the day:
Finding and Cleaning Old Log Files
# Find and delete logs older than 90 days
find /var/log -name "*.log" -type f -mtime +90 -delete
# Find large log files for investigation
find /var/log -type f -size +100M -exec ls -lh {} \;
That first command is now in my crontab, running weekly. It’s saved me from “disk full” disasters more than once.
Finding Recently Modified Configuration Files
# Find config files changed in the last hour find /etc -name "*.conf" -mmin -60
Perfect for debugging when something suddenly breaks after a config change.
Finding Empty Files and Directories
# Find empty files find /home/alice -type f -empty # Find empty directories find /tmp -type d -empty
I use this for cleanup operations and identifying directories that can be safely removed.
Finding Duplicate Files by Name
# Find files with the same name in different directories find /home -type f -name "config.json" 2>/dev/null
The 2>/dev/null redirects error messages (like “Permission denied”) to oblivion, so you only see results.
Finding Files and Searching Their Contents
Combine find with grep to search file contents:
# Find Python files containing "TODO"
find . -name "*.py" -exec grep -H "TODO" {} \;
# Or using xargs for better performance
find . -name "*.py" -print0 | xargs -0 grep "TODO"
This is incredibly useful for code archaeology. If you want to dive deeper into grep, I’ve written a comprehensive guide on Linux grep command examples that covers advanced pattern matching.
Optimizing Find Performance
Limiting Search Depth
Searching your entire filesystem can be slow. Limit the depth:
# Search only 2 levels deep find /home -maxdepth 2 -name "*.txt" # Search only in the specified directory (not subdirectories) find /etc -maxdepth 1 -name "*.conf"
Excluding Directories from Search
Skip directories you don’t need to search:
# Skip .git directories find . -path "*/.git" -prune -o -name "*.js" -print # Skip multiple directory patterns find . \( -path "*/node_modules" -o -path "*/.venv" \) -prune -o -name "*.py" -print
This speeds things up massively in project directories with huge node_modules or virtual environments.
Common Find Command Mistakes (I’ve Made Them All)
1. Forgetting quotes around wildcards: This causes shell expansion before find even runs.
# Wrong find . -name *.txt # Right find . -name "*.txt"
2. Not escaping special characters: Parentheses and semicolons need escaping in most shells.
# Wrong find . ( -name "*.log" -o -name "*.tmp" ) # Right find . \( -name "*.log" -o -name "*.tmp" \)
3. Using -delete without testing first: I deleted 500+ files once before realizing my search criteria was wrong. Always test with -print first!
# Test first find . -name "*.tmp" -print # Then delete find . -name "*.tmp" -delete
4. Not handling filenames with spaces: Use -print0 with xargs -0 when dealing with filenames that might contain spaces or special characters.
Quick Reference Cheat Sheet
Here’s a quick reference I keep in my notes app for when I need a reminder:
# Basic searches
find . -name "filename" # Find by exact name
find . -iname "filename" # Case-insensitive
find . -name "*.ext" # By extension
find . -type f # Files only
find . -type d # Directories only
# By properties
find . -size +100M # Larger than 100MB
find . -mtime -7 # Modified in last 7 days
find . -user alice # Owned by user alice
find . -perm 0644 # Specific permissions
# Actions
find . -name "*.tmp" -delete # Delete matches
find . -name "*.sh" -exec chmod +x {} \; # Execute command
# Performance
find . -maxdepth 2 # Limit depth
find . -path "*/dir" -prune # Exclude directories
Final Thoughts
The find command might seem intimidating at first with all its options and syntax quirks, but it’s absolutely worth mastering. I use it almost daily for everything from debugging production issues to cleaning up my local development machine.
Start with the basic name searches, then gradually incorporate more advanced features as you need them. Before you know it, you’ll be chaining together complex find operations that would have taken hours of manual work.
And hey, if you ever accidentally delete something important with find -delete, don’t say I didn’t warn you. Test first, delete second. That’s a lesson I learned the expensive way.
If you’re dealing with permission issues on the files you find, my complete chmod guide will help you understand how to fix them. And if you’re troubleshooting system issues where you need to search through logs, don’t forget that grep is your best friend for pattern matching within files.
Now go forth and find all the things! And maybe grab another coffee first—you’re going to need it for those deep filesystem searches.