TechEarl

find vs locate vs mlocate: Which File Search Tool to Use

find walks the live filesystem every time it runs: always current, sometimes slow. locate queries a prebuilt database: instant, but stale until the next updatedb. This breaks down the locate family (mlocate, plocate, slocate), the macOS situation, and exactly when to reach for each one.

Ishan KarunaratneIshan Karunaratne⏱️ 14 min readUpdated
find walks the live filesystem every time; locate and plocate query a prebuilt updatedb database. Compare freshness, speed, permission-awareness, and filtering, plus the mlocate vs plocate split and the macOS mdfind alternative.

find and locate both answer "where is that file", but they work in opposite ways. find walks the live filesystem on every run: it opens directories, reads entries, and tests each one against your expression. The result is always current, but on a large tree it can take seconds to minutes. locate skips the walk entirely. It queries a database that was built earlier by updatedb, so a query returns in milliseconds, but the answer is only as fresh as the last database build (typically a once-a-day cron job).

That tradeoff (live walk versus prebuilt index) is the whole decision. If you need a file created five minutes ago, or you need to filter by size, time, or permission, find is the only correct tool. If you just want to recall where nginx.conf lives on a huge box and you will run the query a few times, locate or its modern replacement plocate is far faster. This page is the comparison I reach for when deciding which one to type.

Set your values

Try it with your own values

Set your OS and the file you are searching for. Every command below updates with your values.

The core distinction

find is a filesystem crawler. Every invocation re-reads the directory tree from disk. Nothing is cached between runs. That is why find always reflects the current state of the disk, including files created one second ago, and why a find / on a server with millions of inodes is slow.

locate is a database client. The database is a compact, sorted list of every path on the system, generated by a separate program called updatedb. A locate query is a substring (or glob) match against that list. No directory is opened, no inode is read. The cost is freshness: any file created, moved, or deleted since the last updatedb run is invisible (or wrongly listed) until the database is rebuilt.

bash· Linux (GNU)
# find: walks the live filesystem now
find / -name ':search_term' -type f 2>/dev/null

# locate: queries the prebuilt database (instant)
locate :search_term

The 2>/dev/null on the find command discards permission-denied noise from directories you cannot read. locate has no such noise because it never touches the filesystem.

The locate family: GNU locate, slocate, mlocate, plocate

"locate" is not one program. It is a lineage of implementations, and which one you have depends on your distro and its age.

  • GNU locate (part of findutils) is the original. Its database stores every path it indexed, so any user querying it could see filenames anywhere on the system, including paths inside directories they have no permission to read. That is an information leak.
  • slocate ("secure locate") was the first fix. It stored permission data alongside paths and filtered results so a user only saw files they could actually reach. It is largely historical now.
  • mlocate ("merge locate") became the long-time default on most Linux distros. It is permission-aware like slocate, and its updatedb is efficient because it reuses the existing database and only re-stats directories whose timestamps changed ("merging" the old index with filesystem changes). For most of the 2010s, mlocate was simply what locate meant on Debian, Ubuntu, Fedora, and RHEL.
  • plocate ("posix locate", or practically "fast locate") is the modern replacement. It uses a compressed posting-list index and is dramatically faster on large databases, often returning results before mlocate has finished reading its database file. It is permission-aware. plocate is the default on Debian 12 and later and Ubuntu 23.04 and later, where the locate command now points at it.

On a current Debian or Ubuntu box, locate is almost certainly plocate. On older or RHEL-family systems it is usually mlocate. Run locate --version (or check what which locate resolves to) if you need to know for sure. The query syntax is the same across all of them, so scripts written for mlocate keep working under plocate.

find vs locate vs plocate compared

Propertyfindlocate / mlocateplocate
FreshnessAlways currentStale until next updatedbStale until next updatedb
Speed on large treesSlow (full walk)FastVery fast
SearchesName, type, size, time, perms, content via -execPath name onlyPath name only
Searches file contentOnly via -exec grepNoNo
Permission-awareYes (sees what the calling user sees)Yes (mlocate/slocate); GNU locate noYes
Needs a prebuilt databaseNoYesYes
Can filter by size / time / permYesNoNo
Can run a command on matchesYes (-exec, -delete)No (pipe to xargs)No (pipe to xargs)
Default on modern Debian/UbuntuAlways presentPre-2023Debian 12+, Ubuntu 23.04+

The shape of the table is the decision: find is the everything tool that pays for it in speed; the locate family trades freshness and filtering for near-instant name lookups.

updatedb: how the locate database stays current

locate is only useful because something keeps its database fresh. That something is updatedb, which walks the filesystem (slowly, like find) and writes the index. On a default install it runs once a day from cron or a systemd timer:

  • Debian/Ubuntu mlocate/plocate: a daily job under /etc/cron.daily/ (or a plocate-updatedb.timer systemd unit on newer systems).
  • RHEL/Fedora mlocate: /etc/cron.daily/mlocate.

The config file (/etc/updatedb.conf) controls what gets indexed: PRUNEPATHS excludes directories like /tmp and /var/spool, and PRUNEFS excludes filesystem types like nfs, proc, and sysfs. If locate cannot find something you know exists, check that file before assuming the database is broken.

When you need the database current right now (you just installed a package, or created a file you want locate to see), rebuild it by hand:

bash· Linux (GNU)
# Rebuild the locate database now (needs root)
sudo updatedb

# Then the query sees freshly-created files
locate :search_term

updatedb is itself a full filesystem walk, so running it is exactly as slow as the find you were trying to avoid. The win is amortization: you pay the walk once per day, then every locate query that day is free.

macOS: locate exists, but mdfind is the real tool

macOS ships a locate command (it descends from the BSD original), but the database is not built by default. A fresh locate query on macOS returns "locate: database too small" or nothing at all until you build it once with sudo /usr/libexec/locate.updatedb. After that, a locate.updatedb LaunchDaemon keeps it refreshed on a weekly-ish schedule, not daily.

In practice, on macOS I do not use locate at all. macOS has Spotlight, and Spotlight's command-line interface is mdfind. It queries the Spotlight metadata index, which the OS keeps continuously up to date as files change, so it has none of locate's staleness problem, and it can search file content and metadata, not just names.

bash· Linux (GNU)
# Linux has no mdfind; locate or plocate is the fast-search tool
locate :search_term

So the macOS hierarchy is: mdfind for fast interactive search, find for precise filtering and scripts, and locate only if you specifically want the BSD locate behavior and have built its database.

When to use find

Reach for find when correctness matters more than speed, or when you need anything beyond a name match:

  • Filtering by size, time, or permission. locate only matches path names. find /var/log -size +100M -mtime +7 has no locate equivalent.
  • Acting on matches. find ... -exec and find ... -delete run commands on results. locate can only print paths (you would pipe to xargs, which is fine, but the filtering still has to be a name match).
  • Freshly-created files. Anything created since the last updatedb is invisible to locate. find sees it immediately.
  • Scripts that must be exact. A cron job, a deploy hook, or a cleanup script cannot tolerate a stale index. Use find so the result reflects the disk at the moment the script runs.
  • Searching file content. locate indexes names only. To search inside files you need find ... -exec grep or, better, find + grep together.

If the task involves the words "size", "modified", "older than", "owned by", "delete", or "and then run", it is a find job.

When to use locate or plocate

Reach for locate/plocate when you are doing interactive recall and speed is the point:

  • "Where is that file" lookups by name. You know the filename, you do not know the path, and you want the answer now. locate nginx.conf beats find / -name nginx.conf by orders of magnitude.
  • Repeated queries. If you will run several name searches in a session, the prebuilt index pays off every time. The find walk would repeat the full disk read on each run.
  • Huge filesystems. On a box with tens of millions of files, a find / walk can take minutes. locate answers from the index regardless of tree size.
  • You are fine with day-old data. System binaries, config files, and installed packages do not move often. For those, the daily updatedb cadence is plenty fresh.

The mental model: locate is for "I know roughly what it is called, remind me where it lives." If that describes the task, and the file is not brand new, locate wins.

When to use neither

Sometimes the right answer is a different tool entirely:

  • macOS interactive search: mdfind (covered above). Always current, searches content, no database to maintain.
  • Modern interactive find: fd is a Rust-based find alternative with much friendlier defaults. fd nginx is a recursive, case-smart, regex search with no -name boilerplate. It respects .gitignore by default (great inside repos, occasionally surprising), uses colored output, and runs in parallel so it is fast even though it walks the live tree. For day-to-day "find me this file" at the terminal, fd is the one I actually type. It does not replace find in scripts (the flag set is different and find is universally present), but for interactive use it is the better experience.
  • Content search: if you are searching for a string inside files, not for a filename, use ripgrep (rg). It is built for recursively grepping a tree and is far faster than find ... -exec grep. See the find + grep page for when to combine the two.

fd install is a one-liner: apt install fd-find on Debian/Ubuntu (the binary is fdfind there due to a name clash), brew install fd on macOS, cargo install fd-find anywhere with Rust.

Common mistakes

1. Trusting a stale locate database. The classic trap: locate prints a path, you cd to it, and the file is not there because it was deleted after the last updatedb. Or worse, locate misses a file that exists. If the result has to be accurate, either run sudo updatedb first or use find.

2. Expecting locate to find files created today. A file you created an hour ago will not appear in locate output until the next updatedb (tonight, on a default install). This is not a bug; it is how the index works. Use find for anything recent.

3. Expecting locate to filter by size or time. There is no locate -size or locate -mtime. The database stores path names, nothing else. Size, time, type, and permission filtering all require find.

4. Forgetting macOS does not build the locate DB. A locate query on a fresh Mac returns nothing useful. You must run sudo /usr/libexec/locate.updatedb once, or just use mdfind.

5. Assuming locate and plocate need different syntax. They do not. The query syntax is identical, so the muscle memory carries over when a distro upgrade swaps mlocate for plocate underneath you.

6. Using locate in a script. A script that depends on locate depends on a database that may be hours stale and may not exist at all on a minimal container image. Scripts should walk the filesystem with find so the result is real.

See also

FAQ

TagsfindlocatemlocateplocateCLILinuxmacOS
Share
Ishan Karunaratne

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years across software, Linux systems, DevOps, and infrastructure — and a more recent focus on AI. Currently Chief Technology Officer at a tech startup in the healthcare space.

Keep reading

Related posts

grep is universal and searches everything you point it at; ripgrep (rg) is the fast Rust default that skips .gitignore'd and binary files; ag is the older fast-grep now superseded. Compare speed, defaults, and regex engines.

grep vs ripgrep vs ag: Which Search Tool to Use

grep is on every system and searches exactly what you point it at. ripgrep (rg) is the fast Rust-based default for code search: it skips .gitignore'd, hidden, and binary files unless told otherwise. ag (the_silver_searcher) was the older fast-grep, now largely superseded by ripgrep. This breaks down speed, defaults, regex engines, and exactly when to reach for each one.

find -exec ... {} + batches arguments into one command (fast). find ... -exec ... {} \; forks per file (slow). xargs adds shell flexibility but needs -0 for safety. The decision matrix and performance comparison.

find -exec vs xargs: Which to Use (and the {} + Trick That Beats Both)

find -exec ... {} + and find -print0 | xargs -0 are roughly equivalent for batch operations on matched files. find -exec ... {} \; forks once per match and is much slower. The decision matrix: when -exec is enough, when xargs adds value, and the safety rules for filenames with spaces, newlines, and quotes.

find -delete removes every matched file with no confirmation. The safe -print-first dry-run pattern, depth-first directory deletion, when to use -exec rm vs xargs rm -f, and the BSD vs GNU differences.

How to Find and Delete Files Safely with find -delete

find -delete removes every matched file with no confirmation and no undo. The safe pattern is to write the command with -print first, eyeball the list, then swap -print for -delete. Plus the directory-depth-first trap, when to use -exec rm instead, and the find -delete vs xargs rm -f tradeoff.