Find Files on Linux
The find command is the standard way to find files on Linux: it walks a directory tree, tests each entry against the predicates you give it, and prints or acts on the matches, covering name, size, and age in a single pass.

On a typical web server it is the first tool you reach for when a file has vanished, a log has exploded, or a user quota needs a second look, and a single invocation can search the whole Linux file system in under 60 seconds on a modern SSD.
The command ships in the GNU coreutils world on most distributions, but its home is the Linux Kernel interface to the filesystem, because every test you run underneath it is a kernel operation, from stat calls to directory reads. That is why the same syntax works on a Raspberry Pi and a 64 core box. Most Linux Commands you will type in a shell, such as ls, grep and du, only inspect what is already in front of them, while find goes looking. It also respects the owner and permission bits it reports, which matters when you are hunting for a file left behind by a deleted account among your Linux User Accounts, because the entry still carries the numeric user ID even after the name is gone.
How the search works
How the search works comes down to three moving parts: the starting path, the expression, and the action. The default starting point is ., the current directory, and the default action is -print. Everything else is built by chaining predicates with the operators -a (and), -o (or), and ! (not). You can see the order of operations with -ls, which shows the same metadata ls -l shows for a single file, and you can watch the walk itself with -print0 piped to xargs so that names with spaces or newlines survive the trip.
- Path: the directory tree the walk begins in, for example
/var/www - Expression: the predicates joined by and, or, and not
- Action:
-print,-ls, or-delete, one per matching file
Keep the three apart and a query stays readable, and when you do need to delete, run the same expression with -print first and only flip to -delete after the list looks right.
Flags by flag
The flags by flag are grouped below by what they match, and the table is the fastest way to build a query: pick a row for the attribute you care about, then chain the rows together.
| Flag | Matches | Example |
|---|---|---|
-name | filename, supports * and ? | -name "*.php" |
-iname | filename, case-insensitive | -iname "readme" |
-path | full path, supports * | -path "*/logs/*" |
-type | entry kind, such as f file, d dir, l link | -type f |
-size | size in 512 byte blocks, or k, M, G units | -size +10M |
-mtime | days since modification, -n newer, +n older | -mtime +30 |
-mmin | minutes since modification, same sign rule | -mmin -60 |
-user / -group | owner or group by name or ID | -user www-data |
-perm | mode bits, such as -u+x | -perm -u+x |
Two habits make these flags precise. Size takes 512 byte blocks when you give a bare number, so -size 100 is 51200 bytes, but the k, M and G suffixes skip that arithmetic, and a + or - prefix switches the test to bigger than or smaller than. Time works the same way: -mtime 30 means files changed exactly in the 30th 24 hour window, while +30 is anything older and -1 is anything changed in the last day.
Finding files by name
Finding files by name is the most common task, and the difference between -name and -path is the whole lesson. -name only ever looks at the last component, so -name "*.php" matches /var/www/index.php and /var/www/api/v2/index.php alike, while -path tests the entire string and lets you pin a match to a subtree. On a LAMP box where PHP files live in two web roots, the second form is the one that keeps you from deleting the wrong directory.
find /var/www -name "*.php"locates every PHP file under both rootsfind /var/www -path "*/logs/*" -name "*.log"narrows the same walk to log files onlyfind /etc -iname "hosts*" -type fsurfaces the hosts file regardless of its exact case
Case is a frequent source of dead ends, so reach for -iname when you do not know how a developer named the file, and add -type f so that a directory called hosts does not get mixed in with the file you actually want.
Finding files by size and age
Finding files by size and age is where find earns its place over ls, because both are single predicates that chain with anything else. The two questions on a server are almost always the same: what is eating disk space, and what can be safely purged. Size answers the first with -size +100M to flag any file over 100 MB, and age answers the second with -mtime +90 to flag anything untouched for 90 days.
- Find the heavy files:
find /var/log -type f -size +100M -exec ls -lh {} \; - Find the stale files:
find /var/spool -type f -mtime +90 -print - Combine both:
find /var -type f -size +10M -mtime +30 -exec du -h {} \;
The -exec ... \; form runs a command once per match, which is slower, while -exec ... + batches the arguments and is faster on a large tree. For a purge, pair the test with -newermt on a reference date, or with -mmin -60 to keep anything touched in the last 60 minutes, so that a running log never gets caught in the sweep.
Actions and the delete flag
Actions and the delete flag are the part that turns a search into an operation, and the rule is that -delete is implied to be -print replaced, not added. You have three choices for what happens to a match: -print sends the name to standard output, -ls prints a long listing, and -delete removes the entry. The safe pattern is to run the exact same expression twice, first with -print to review the list, then with -delete once you trust it, and to prefer -exec rm {} + when you want the removal to respect a command rather than the built in.
One more guardrail: -delete cannot be used with -exec in the same expression, and it fails on a directory that is not empty, so delete top down or use -depth to process children first. When the matches are user owned, check the owner with -user before you touch anything, because a file left behind by a Linux User Accounts migration is yours to clean up, and a file belonging to a live service is not.
Working with the hosts file
Working with the hosts file is a small but recurring task that find handles without special treatment. The hosts file is a plain text name resolution database that the system consults before it asks a name server, and on most distributions it lives at /etc/hosts, with per interface overrides possible under /etc/hosts.d on some setups. Locating it across a fleet is a one liner, and locating its siblings is the habit that pays off.
find /etc -name "hosts" -type ffinds the primary hosts filefind / -name "hosts" -type f 2>/dev/nullfinds every copy, including chroot jailsfind /etc -name "hosts*" -newermt "2026-08-01" -printfinds any copy changed since a given date
On a container host the second command is the one that matters, because each container carries its own copy under /etc/hosts inside its own mount namespace, and the 2>/dev/null keeps the permission denied noise from a thousand unreadable paths out of your terminal.
Server-ready examples
Server-ready examples are the ones you can paste into a runbook and trust. The four below cover the recurring jobs on a LAMP server, and each one is built from the flags above, so the pattern transfers to your own paths and thresholds. The web root is /var/www, the service user is www-data, and the log directory is /var/log.
- Find PHP files over 5 MB:
find /var/www -type f -name "*.php" -size +5M -ls - Find world writable files, the classic audit:
find /var/www -type f -perm -o+w -ls - Find logs changed in the last 10 minutes:
find /var/log -type f -mmin -10 -print - Find files owned by a vanished user ID 1042:
find / -uid 1042 -print 2>/dev/null
Two final notes keep these safe in production. Redirect the noise with 2>/dev/null so that permission denied lines do not drown the real matches, and cap the walk with -maxdepth 3 when you only need the top of the tree. The hosts file, the web root, the log directory, and the user namespace all fall out of the same four predicates, which is why the command still earns a place on every server that runs a Linux Kernel older or newer than the one you are reading this on.