The Linux find Command: A Practical Guide with Examples
July 07, 2026 — LiveStream

Disclosure: some links above are affiliate links — if you buy through them I may earn a small commission at no extra cost to you. Thanks for supporting the channel!
The Linux find command is a true workhorse in any system administrator's or DevOps engineer's toolkit, providing unparalleled power to locate files and directories based on a myriad of criteria. From routine cleanup of old logs to critical security audits and sophisticated automation scripts, mastering find is absolutely indispensable for efficient file management on Linux systems. This comprehensive guide will demystify find, taking you from its basic syntax to advanced patterns and real-world one-liners you'll integrate into your daily workflow.
Yaar, when you're knee-deep in server administration, the sheer volume of files can be overwhelming. You might need to find every log file older than 30 days, identify all files larger than 1GB taking up disk space, or perhaps delete all temporary files across a complex directory structure in one shot. This is precisely where the Linux find command shines. It’s like a super-efficient search assistant that not only locates files but can also perform actions on them, making it one of the most powerful and flexible utilities at your disposal. Let’s dive deep into how to wield this command like a pro.
Understanding the Core Syntax: `find [path] [conditions] [actions]`
At its heart, the find command follows a simple yet incredibly flexible structure: you tell it where to look, what to match, and what to do with the matches. If you omit the "what to do" part, find will simply print the paths of the files and directories that meet your specified conditions.
[path]: This is the starting point for your search. It can be a specific directory (e.g.,/var/log,/home/user) or the current directory (.). If omitted, it defaults to the current directory.[conditions]: These are the criteriafinduses to filter files. This is where the real magic happens, allowing you to specify names, types, sizes, modification times, permissions, owners, and much more.[actions]: Once a file matches the conditions,findcan perform an action on it. This could be printing its path (the default), deleting it, executing another command, or changing its permissions.
Let's start with a very basic example. To list every file and directory under your current working directory, you'd simply run:
find .
This command starts searching from the current directory (.) and, with no specific conditions or actions, will print the path of every file and directory it encounters recursively. Pretty straightforward, right?
Finding by Name: Precision in Search
One of the most common ways to search for files is by their name or a part of their name. The -name and -iname options are your go-to for this.
-name "pattern": Matches files whose base name (the file name itself, not including the path) matches the specifiedpattern. This match is case-sensitive.-iname "pattern": Similar to-name, but the match is case-insensitive. This is super handy when you're not sure about the exact casing, like `README.md` vs `readme.md`.
A Critical Note on Wildcards: Always, always, always quote your patterns when using wildcards (*, ?, []) with find. If you don't, your shell (like Bash) might try to expand the wildcard *before* passing it to find. This can lead to unexpected results or errors if no files in your current directory match the wildcard. For example, find . -name *.log could expand to find . -name file1.log file2.log if those files exist in the current directory, which is probably not what you intended.
Examples:
- Files ending in
.log(case-sensitive):find . -name "*.log" - Files starting with "config" (case-insensitive):
find /etc -iname "config*" - Searching for a specific file name, say
my_app.conf, within a specific path:find /var/www/html -name "my_app.conf" - Finding files that contain "report" anywhere in their name:
find . -iname "*report*"
Finding by Type, Size, and Time: Refining Your Search
Beyond names, find allows you to filter results based on their fundamental attributes like file type, size, and modification times. This is where its power truly begins to shine for system maintenance tasks.
Finding by Type (`-type`):
Files aren't just "files." Linux recognizes different types. The -type option lets you specify exactly what kind of entry you're looking for:
f: Regular filed: Directoryl: Symbolic linkb: Block device (e.g., hard drives)c: Character device (e.g., serial ports)p: Named pipe (FIFO)s: Socket
Examples:
- Only directories in the current path:
find . -type d - Only regular files:
find . -type f - Only symbolic links in
/usr/bin:find /usr/bin -type l
Finding by Size (`-size`):
This condition is a lifesaver when you're trying to locate large files hogging disk space. The -size option takes a number followed by an optional unit. Without a unit, it defaults to 512-byte blocks.
c: Bytesk: Kilobytes (1024 bytes)M: Megabytes (1024 KB)G: Gigabytes (1024 MB)
You can also use prefixes:
+N: Greater thanNunits.-N: Less thanNunits.N: ExactlyNunits (rarely used, as exact size is uncommon).
Examples:
- Files larger than 100 MB:
find . -type f -size +100M - Files smaller than 1 KB:
find /tmp -type f -size -1k - Files exactly 50 bytes (for very specific scenarios):
find . -type f -size 50c
Finding by Time (`-mtime`, `-ctime`, `-atime`, `-mmin`, `-cmin`, `-amin`):
Timestamp-based searches are incredibly powerful for log rotation, cleanup scripts, and identifying recently changed files. There are three main timestamps for files in Linux:
-mtime/-mmin: Modification time (when the file's content was last modified).-atime/-amin: Access time (when the file was last read).-ctime/-cmin: Change time (when the file's metadata, like permissions or ownership, or content was last changed).
The -mtime, -atime, -ctime options count in days, while -mmin, -amin, -cmin count in minutes. The prefixes +N and -N have specific meanings here:
+N: Means more than N units ago (e.g.,+7means older than 7 days).-N: Means less than N units ago (e.g.,-7means within the last 7 days).N: ExactlyNunits ago (e.g.,7means between 7 and 8 days ago, not exactly 7 days. This is often confusing, so+Nand-Nare preferred).
Examples:
- Files modified in the last 7 days:
find . -type f -mtime -7 - Log files older than 30 days:
find /var/log -name "*.log" -mtime +30 - Files accessed in the last 60 minutes:
find /home/user -type f -amin -60 - Files whose metadata (permissions, owner, etc.) changed more than 90 days ago:
find /etc -ctime +90
This time-based filtering is foundational for automating tasks like log archiving and temporary file cleanup.
Finding by Permissions and Owner: Security and Management
For security audits, system hardening, or just general file management, being able to search by permissions and ownership is crucial.
Finding by Permissions (`-perm`):
The -perm option is quite powerful but can be a bit nuanced. It takes an octal permission mode or a symbolic mode.
The most common forms are:
-perm mode: Matches files with exactly these permissions. For example,-perm 0644will only match files that arerw-r--r--. This is less common as exact matches are rare.-perm -mode: Matches files where all of the bits inmodeare set. For example,-perm -002means "writable by others."-perm -u+smeans "setuid bit is set for user." This is very useful for security checks.-perm /mode: Matches files where any of the bits inmodeare set. For example,-perm /222means "writable by anyone (user, group, or others)." This is often used to find files with "too open" permissions.
Examples:
- Files with exactly
0777permissions (rwxrwxrwx):find . -perm 0777 - Files with the SetUID bit set (a common security audit concern):
find / -type f -perm -u+s 2>/dev/null(Here,
2>/dev/nullis added to suppress "Permission denied" errors in system paths, which we'll discuss in pitfalls.) - Files writable by "others" (group or world writable):
find . -perm /g+w,o+wOr using octal:
-perm /002(world writable) or-perm /022(group or world writable). - Directories that are not executable by others (
-xfor not executable):find . -type d ! -perm /o+x
Finding by Owner (`-user`, `-group`):
To identify files owned by a specific user or group, these options are your friends.
-user username: Files owned byusername.-group groupname: Files owned bygroupname.-uid N: Files owned by user IDN.-gid N: Files owned by group IDN.
Examples:
- Files owned by user
alicein her home directory:find /home/alice -user alice - Files owned by the
www-datagroup in your web server's root:find /var/www -group www-data
Finding Empty Files or Directories (`-empty`):
This simple condition helps you clean up clutter.
-empty: Finds empty files or empty directories.
Example:
find /tmp -empty
Doing Something with the Results: `-exec` and `xargs` – The True Power of `find`
Locating files is one thing, but performing actions on them is where find transforms from a search tool into a powerful automation engine. The primary ways to do this are with -exec and piping to xargs.
Using `-exec` to Run Commands
The -exec action allows you to execute a specified command on each file found. The placeholder {} represents the current file being processed, and the command must be terminated by \; (escaped semicolon) or +.
`find ... -exec command {} \;` (One command per file)
This variant runs the specified command once for *each* file found. This can be slower for a large number of files, as it involves spawning a new process for every single match. However, it's safer if the command you're executing can only handle one argument at a time or has specific requirements.
Examples:
- Delete all
.tmpfiles:find . -name "*.tmp" -exec rm {} \;Caution: Always run
find . -name "*.tmp"first to preview the files before adding-exec rm {} \;! - Change permissions of specific log files:
find /var/log -name "*.log" -mtime +7 -exec chmod 640 {} \; - Run
staton each found file to get detailed info:find . -type f -exec stat {} \;
`find ... -exec command {} +` (Batching for Speed)
This is often the preferred method when you're executing a command that can accept multiple arguments at once (like `rm`, `gzip`, `ls`, `chmod`). Instead of running the command for each file, find builds up a list of found files and passes them as arguments to a single instance of the command, or as few instances as possible. This is significantly faster for a large number of files.
Examples:
- Gzip all
.logfiles older than 7 days, in a batch:find /var/log -name "*.log" -mtime +7 -exec gzip {} + - List details of all files larger than 500MB:
find . -type f -size +500M -exec ls -lh {} + - Fix directory permissions only:
find . -type d -exec chmod 755 {} +
Piping to `xargs`: The Robust Solution for Special Characters
While -exec ... + is great, sometimes you need even more flexibility or robustness, especially when dealing with filenames containing spaces or other special characters (like newlines). This is where xargs comes in. The key is to use -print0 with find and -0 with xargs.
-print0(withfind): This tellsfindto output filenames separated by a null character (\0) instead of a newline.-0(withxargs): This tellsxargsto expect null-terminated input.
This combination ensures that filenames with spaces, newlines, or other troublesome characters are correctly processed as single arguments, making your scripts much more robust.
Example: Delete all .bak files, safely handling spaces in names:
find . -name "*.bak" -print0 | xargs -0 rm
Another example: Copy all `.jpg` files found in `/path/to/photos` to `/backup/images`:
find /path/to/photos -type f -name "*.jpg" -print0 | xargs -0 cp -t /backup/images/
(The -t option for cp allows specifying the target directory before the source files, which is useful with `xargs`.)
Combining Conditions: Building Complex Queries
Real-world scenarios rarely involve just one condition. find allows you to combine multiple conditions using logical operators.
- Implicit AND: By default, if you list multiple conditions,
findtreats them as anANDoperation.find . -type f -name "*.sh"This finds regular files (
-type f) AND whose name ends with.sh(-name "*.sh"). - OR (`-o`): Use
-oto specify anORcondition.find . -name "*.jpg" -o -name "*.png"This finds files named
.jpgOR.png. - NOT (`!`): Use
!to negate a condition. Remember to escape it or quote it for the shell.find . -type f ! -name "*.txt"This finds regular files that are NOT named
*.txt.find . -type d ! -perm /o+wThis finds directories that are NOT world-writable.
- Grouping with Parentheses: For more complex logic, you can group conditions using parentheses
\( ... \). Remember to escape the parentheses so the shell doesn't interpret them.find . \( -name "*.log" -o -name "*.tmp" \) -mtime +7 -printThis finds files named
.logOR.tmp, AND are older than 7 days.
Controlling Search Depth: `maxdepth` and `mindepth`
Sometimes you don't want to search the entire subtree or you want to skip certain levels. These options come in handy:
-maxdepth N: Limits the search to a maximum depth ofNlevels below the starting point.-maxdepth 0means only the starting point itself.-maxdepth 1means only the starting point and its direct children (files/directories directly inside it).-mindepth N: Only applies conditions and actions to files/directories at leastNlevels deep.-mindepth 1skips the starting directory itself.
Examples:
- List only files in the current directory, no recursion:
find . -maxdepth 1 -type f - Find directories at least 2 levels deep, but no more than 3 levels:
find . -mindepth 2 -maxdepth 3 -type d
Real-World One-Liners for DevOps Engineers
Let's look at some practical scenarios that illustrate the power of find in a DevOps context.
- Clean up log files older than 14 days and ending with
.log:find /var/log -type f -name "*.log" -mtime +14 -deleteThe
-deleteaction is a specialized-exec rm {} \;, but it's generally more efficient for simple deletions. Still, always preview first! - Find the biggest files (over 500MB) in a directory and list them with human-readable sizes:
find . -type f -size +500M -exec ls -lh {} + - Fix directory permissions only (set to 755) while keeping file permissions (say, 644):
find . -type d -exec chmod 755 {} +find . -type f -exec chmod 644 {} + - Find files modified since a reference file (`/tmp/marker`):
touch /tmp/marker # Create a reference point # Do some operations find . -newer /tmp/marker -type fThe
-newercondition compares the modification time of the found file with that of the reference file. - Find all empty directories and remove them (after confirming they are truly empty):
find . -type d -empty -exec rmdir {} \;rmdironly removes empty directories. If a directory isn't truly empty (e.g., contains hidden files), `rmdir` will fail, which is a good safety net. - Find files with a specific string inside them (using `grep`):
find . -type f -name "*.conf" -print0 | xargs -0 grep "DB_PASSWORD"This is a common pattern: `find` to locate candidate files, then `xargs` to pipe them to `grep` for content inspection.
Common Pitfalls and How to Avoid Them
Even though find is powerful, it has its quirks. Being aware of these common mistakes will save you headaches, yaar.
- Unquoted Wildcards: As mentioned, this is a big one.
find . -name *.log # BAD! Shell expands *.log BEFORE find sees it.find . -name "*.log" # GOOD! find processes the wildcard.Always quote your patterns (`"*.log"`) to ensure the shell passes the wildcard literally to
find. - Spaces in Filenames: If you're using
find ... | xargs ...without-print0and-0, filenames with spaces will be split byxargsinto multiple arguments, causing errors.find . -name "*.txt" | xargs rm # DANGER with "my file.txt"find . -name "*.txt" -print0 | xargs -0 rm # SAFE and recommended - `find ... -delete` is Irreversible: This is a big one! Once you use
-delete, the files are gone. There's no undo.find /var/log -name "*.old" -delete # No going back!Always, always run the
findcommand without-delete(or-exec rm {} \;) first to preview the matched files. Only add the deletion action once you're absolutely certain. - `mtime` and `amin` Confusion: The interpretation of
+Nand-Nfor time can be tricky.-mtime +7: More than 7 days ago (i.e., 8 days old or older).-mtime -7: Less than 7 days ago (i.e., 0 to 6 days old, including today).-mtime 7: Exactly 7 days ago (i.e., between 7 and 8 days old).
Be very clear about your date ranges to avoid accidentally deleting fresh data or missing old data.
- "Permission denied" Noise: When searching system directories as a non-root user, you'll often encounter "Permission denied" errors.
find / -name "*.conf" # Lots of "Permission denied" errorsTo suppress these error messages (which are sent to standard error, file descriptor 2), redirect them to
/dev/null:find / -name "*.conf" 2>/dev/nullHowever, be mindful that suppressing errors might hide actual issues if you're expecting certain files to be found in restricted areas. Use
sudoif appropriate and you need to search root-owned directories comprehensively.
Key Takeaways
- The
findcommand is a versatile tool for locating files and directories based on various attributes like name, type, size, time, permissions, and owner. - Its basic syntax is
find [path] [conditions] [actions], allowing you to specify where to search, what criteria to match, and what operation to perform on the matches. - Always quote patterns with wildcards (e.g.,
"*.log") to prevent shell expansion and ensure `find` processes them correctly. - Utilize
-exec(with\;for per-file commands or+for batching) or pipe toxargs -0(with-print0) for efficient and safe execution of commands on found files, especially with filenames containing spaces. - Be extremely cautious with deletion actions (
-deleteor-exec rm {} \;); always preview the results first by running thefindcommand without the destructive action.
Frequently Asked Questions
What's the difference between `find ... -exec command {} \;` and `find ... -exec command {} +`?
The key difference lies in performance and how arguments are passed. -exec command {} \; runs the specified command once for *each* found file, spawning a new process every time. This can be slow for many files. In contrast, -exec command {} + collects all (or many) found files and passes them as a single list of arguments to one (or very few) instances of the command. This batching makes it significantly faster for large sets of files when the command supports multiple arguments (like `rm`, `ls`, `chmod`, `gzip`).
How do I find files modified in the last hour?
You can use the -mmin option, which operates in minutes. To find files modified in the last 60 minutes (the last hour), you'd use:
find . -mmin -60 -type f
The -60 means "less than 60 minutes ago," effectively within the last hour.
Why does `find` spew "Permission denied" errors, and how can I stop them?
find reports "Permission denied" errors when it tries to access directories or files for which your current user lacks read permissions. This is common when searching system-wide paths (like /, /proc, /sys) as a non-root user. To suppress these errors, redirect standard error (file descriptor 2) to /dev/null:
find / -name "*.log" 2>/dev/null
If you genuinely need to search restricted areas, consider running find with `sudo` (e.g., sudo find / -name "*.log"), but use `sudo` with caution.
`find` vs `locate` vs `grep` – Which one should I use?
find: Scans the filesystem live. Always accurate, but can be slower, especially on large directories. It's the most powerful, allowing complex conditions (size, time, permissions, type) and actions (-exec). Usefindfor precise, real-time queries and when you need to perform actions on the results.locate: Queries a pre-built database (mlocate.dbor similar) which is updated periodically by cron jobs. It's almost instant because it doesn't scan the live filesystem, but the results can be stale (not showing very recent changes) and it's primarily for name-based searches, with limited conditional logic. Uselocatefor quick, rough name lookups across the entire system.grep: Searches *inside* files for patterns of text. It doesn't find files themselves; it reads their content. Often used in conjunction withfind(e.g.,find ... -exec grep ...orfind ... | xargs grep ...) to first locate files, then search their contents. Usegrepwhen you need to find text *within* files.
Mastering the Linux find command is a journey, not a destination. With its rich set of condition flags, powerful -exec action, and robust integration with xargs, it becomes that Swiss-army knife you constantly reach for whenever you're thinking, "Boss, where is that file?" or "Time to clean these old logs, yaar." Keep these examples and pitfalls in mind, practice regularly, and you'll soon be automating file management like a seasoned pro. Dekho, it's all about making your life easier!
For more detailed demonstrations and live examples, make sure to watch the full video on the find command and subscribe to @explorenystream for more amazing DevOps content!