Find large files on a Mac: choose the starting point
The disk is nearly full, and the instinct from a Windows machine is to type a size filter into the search box and let the file manager sort it out. On a Mac that instinct produces either nothing at all or a list that misses the folder actually holding the weight. The search behaves differently, the command line reports in a unit nobody expects, and several of the biggest directories refuse to be counted. Each of those is fixable, but only once you know which one is in play.
The habits that do not transfer
File Explorer accepts a size term directly in the search box, and the buckets it offers are coarse but instant. Finder has an equivalent, but it is not typed into the search field. It lives behind the plus button that appears after a search has started, where a criterion row can be set to File Size, greater than, and a number with a unit.
The difference that matters is scope. A Finder search covers what Spotlight has indexed, which is not the same as what is on the disk. Volumes can have indexing switched off, and a disk image mounted for a single job usually does. Running mdutil -s -a lists every mounted volume with its state, and a line reading Indexing disabled. is the explanation for a search that returns nothing from a drive you can see in the sidebar.
The second difference is that Finder measures files, not folders. A folder holding twenty thousand small files never appears in a size search, no matter how much space it occupies in total. On a Windows machine the same blind spot exists, but the folder tree tends to be shallower, so it hurts less. On a Mac the deep, invisible trees under the user Library are exactly where the space goes.
Decide three things before typing a command
Every command in this article is a variation on the same three decisions, and getting them wrong is what produces the scans that run for ten minutes and answer nothing.
The starting point. Scanning from the root of the disk is almost always the wrong choice. Most of it is the read only system volume, which you cannot change, and the parts you can change sit in one or two places. Starting from the home folder, or from a single suspect directory inside it, turns a ten minute scan into a ten second one.
The threshold. A threshold that is too low buries the answer. On a working machine, a list of everything over 100 MB can run to hundreds of lines. Starting at 1 GB and lowering it only if the list comes back short is faster than reading a long list.
The unit. This is the one that catches people, and it is covered in its own section below, because the default is not what anyone expects.
There is a fourth decision that only matters once: whether you are looking for one enormous file or for a folder that has quietly accumulated. Those need different commands, and running the wrong one is why a scan can report nothing while the disk stays full.
The unit du reports in is not megabytes
du with no flags reports in 512 byte blocks. A directory holding a single 100 KB file comes back as 200. That number is not wrong, and it is not kilobytes, and reading it as kilobytes puts every estimate out by a factor of two.
The flags that fix it are single letters. -k reports in kilobytes, -m in megabytes, and -h in the human readable form that picks a unit per line. -h is the one to use interactively, and it composes with sort -h, which orders those mixed units correctly, so du -h -d 1 ~/Documents | sort -h puts the heaviest subfolder at the bottom of the output where the eye lands.
Two more flags earn their place. -d 1 limits the report to one level down, which is what you want when the question is "which subfolder", rather than a line for every directory in the tree. -x keeps the scan on a single file system, so it will not wander into a mounted disk image or an external drive and spend minutes there.
Scanning is slower than it looks. On one working Mac, du -x -d 1 -h ~/Library took over two minutes to return, and the answer it gave was worth the wait: Application Support at 360 GB, Containers at 142 GB, and Caches at 85 GB, out of 716 GB for the Library folder as a whole. None of those three would ever appear in a search for large files, because none of them is a file.
Writing the find command so it returns what you meant
find answers the other question: individual files over a size, wherever they are.
The syntax trap is the suffix. find ~ -type f -size +1G means gigabytes, and +500M means megabytes, but a bare find ~ -size +500 means 500 blocks of 512 bytes, which is a quarter of a megabyte. The command runs, returns thousands of lines, and looks like it ignored the filter.
-type f restricts the results to regular files, which stops directories and symbolic links from padding the list. -x keeps the search on one file system, the same as it does for du. Piping the results into -exec ls -lh {} + turns bare paths into a listing with sizes attached, which is usually what you wanted to see in the first place.
Permission noise is worth suppressing early. A scan starting from the home folder will hit directories it cannot enter and print a line for each. Appending 2>/dev/null keeps the output readable, with the caveat covered in the next section: those errors are not always noise.
| Question | Command | Reports |
|---|---|---|
| Which subfolder is heaviest? | du -x -h -d 1 ~/Documents | sort -h |
Totals per subfolder |
| Which single files are huge? | find ~ -x -type f -size +1G |
One path per file |
| How many bytes exactly? | stat -f '%z' name.mov |
An exact byte count |
| Which indexed files are huge? | mdfind 'kMDItemFSSize > 1073741824' |
Paths, from the Spotlight index |
| Is this volume even indexed? | mdutil -s -a |
Index state per volume |
The folders that refuse to be counted
Some directories return Operation not permitted no matter how the command is written. Running du -sh ~/Library/Mail on a recent macOS produces exactly that, and it is not a bug or a sudo problem. Mail, Messages, Safari data and several other locations are protected by the privacy system, and the process asking has to hold Full Disk Access before it can read them.
That matters for the arithmetic. If a scan of the home folder reports 200 GB and the storage pane reports 300 GB, the gap is not necessarily hidden files. Part of it is the folders the scan was refused. Granting Full Disk Access to the terminal application in System Settings, under Privacy and Security, changes the answer rather than merely quieting the errors.
The Spotlight route has a different blind spot. mdfind 'kMDItemFSSize > 1073741824' is fast because the index already knows every file size, and it returns in a second where find takes minutes. It also silently omits anything on a volume where indexing is off, and anything inside a directory whose name ends in .noindex, which is a convention several development tools use for their caches.
What the built in storage pane already knows
Before writing anything, the storage pane has a list ready. The Apple documentation describes what sits behind it:
Documents: See all the documents on your Mac. You can quickly view large files or downloads by clicking the corresponding button, and sort files by clicking Name, Kind, Last Accessed, or Size near the top of the dialog. You can also click File Browser to view the contents and amount of storage used by various folders in your file system.
Source: support.apple.com
The Large Files button in that pane is the quickest first look on a machine where nothing has been investigated yet, and the File Browser view is the graphical equivalent of du -d 1. Its limitation is that it reports what it can attribute to a category, which is why a large System Data figure appears with nothing behind it to click.
One warning about the arithmetic before deleting anything: du reports the logical size of files, so two copies made with the clone option that share their storage are counted twice. Creating a 10 MB file and cloning it with cp -c produces a directory that du calls 20 MB while the free space on the disk barely moves. Deleting one of the two frees nothing.
Checking a candidate before it goes
A path on the screen is not yet a decision. Three cheap checks separate the files that can go from the ones that will be missed, and all three run in less than a second.
The first is the exact size, because the human readable output rounds. mdls -name kMDItemFSSize on a large video file returns a figure like 13592977182, which is the byte count with nothing hidden in the rounding. stat -f '%z' gives the same answer without going through the index.
The second is when it was last touched. ls -lu shows the access time rather than the modification time, which distinguishes a file that was written a year ago and read yesterday from one that nothing has opened since it arrived. The Spotlight equivalent, mdls -name kMDItemLastUsedDate, is worth trying but often returns (null), because the attribute is only recorded for files opened through the usual application paths.
The third is whether anything has it open right now. lsof followed by the path prints nothing when the file is idle and lists the process when it is not. A large file that a running application is still writing to is the worst possible thing to delete, and this is the one second check that catches it.
Extended attributes are a smaller clue in the same direction. xattr followed by the path lists what is attached: entries such as com.apple.macl and com.apple.provenance mark files that arrived through the sandboxed file dialogs, which usually means an application put them there rather than you.
Where the answer stops being useful
The scan finishes, and there is a path on the screen. Now the work starts: look at the file, decide whether it can go, check whether something depends on it, and only then remove it. That sequence crosses windows every time. The path came from a terminal, the preview needs Finder or an application, and the decision sends you back to the terminal to type the path again.
Cutting that round trip is a layout problem rather than a command problem. A file manager that keeps a terminal in the same window has the listing and the prompt pointed at the same directory, so a path found by a command is already selected in the list next to it. What that combination covers is set out on the Features page. For how it compares with the dual pane managers and the Finder replacements that solve part of the same problem, the Compared with other file managers page lays the differences out plainly, and the Pricing page has the terms.
What to change first
Fix the unit before anything else: put -h on every du and a suffix on every -size, and the numbers start meaning what you read them as. Then narrow the starting point to one folder rather than the whole disk, and check whether the terminal has Full Disk Access before trusting any total. If the round trip between finding a file and acting on it is what actually costs the time, Atriens is built for that half.
Frequently asked questions
Why does a Finder size search miss the folder that is clearly using the space?
A size search matches files, not folders. A directory holding twenty thousand small files has no size attribute to match against, so it never appears however large the total is. Use du -x -h -d 1 on the parent folder to see totals per subfolder instead.
What unit does du report in when no flag is given?
512 byte blocks. A folder holding one 100 KB file reports as 200. Add -h for human readable output, -k for kilobytes or -m for megabytes, and pipe -h output through sort -h to order it correctly.
Why does du say "Operation not permitted" on some folders?
Those directories are protected by the privacy system rather than by file permissions, and Mail is the one people hit first. The terminal application needs Full Disk Access, granted in System Settings under Privacy and Security, before it can read them. Until then the totals it reports are short by whatever those folders hold.
Is mdfind faster than find for this, and is there a catch?
It is much faster, because the sizes are already in the Spotlight index rather than being read from disk. The catch is coverage: it returns nothing from volumes with indexing switched off, which you can check with mdutil -s -a, and nothing from directories ending in .noindex.
Deleting a large file freed no space at all. What happened?
The most common cause on APFS is that the file shared its storage with another copy made by cloning, so removing one of the two changes nothing on disk. Snapshots and purgeable caches produce the same appearance. du counts the logical size of both copies, which is why its total can exceed what deleting would actually recover.