If you've ever compared two storage tools' totals for the same folder and found they disagree by a surprising amount, hard links are one of the most common — and least understood — reasons why. This isn't a bug in either tool. It's a genuine ambiguity in what "how much space does this folder use" even means once a single file can have more than one name.

What a hard link actually is

A hard link is not a shortcut or an alias. It's a second directory entry pointing at the same underlying data on disk — the same inode, in filesystem terms. Both names are equally "real"; neither is the original and neither is the copy. If you have two hard-linked files, A/report.pdf and B/report.pdf, they are the same bytes on disk appearing under two paths. Deleting one name does not free any space, because the data is still referenced by the other name. Only when the last remaining link to that data is removed does the space actually become free.

macOS uses hard links extensively in a few specific places: Time Machine's older-style local backups used them heavily to represent unchanged files across snapshots without duplicating the data, and some package formats and system directories use them internally.

The double-counting problem

Here's the ambiguity. If a storage tool walks A and finds report.pdf at 500MB, then walks B and finds report.pdf at 500MB, does it report 1GB in total, or 500MB? Both answers are defensible depending on what you're trying to learn:

  • If you want to know "how much would I free by deleting folder A," then A's contribution should count the full 500MB, because that's what disappears from A's perspective — even though the underlying bytes might survive via B.
  • If you want to know "how much total disk space do A and B occupy together," the honest answer is 500MB, once — counting it twice overstates how much space you'd free by deleting both.

A tool that naively sums file sizes as it walks the tree will double-count (or worse, multiply-count if there are more than two links), reporting more space "used" than the disk actually shows as occupied. This is the single most common reason a storage tool's grand total for a whole-disk scan doesn't match the free-space number in Finder or df -h.

How du handles it

The classic du command has heuristics for this, though behaviour varies by version and flags. On modern implementations, du tracks inode numbers it has already counted within a single invocation, so that a second hard-linked reference to the same inode, discovered later in the same scan, isn't added again. This is why running du -sh on a directory containing internally hard-linked files sometimes reports a smaller total than naively adding up every file's reported size would suggest.

The important caveat: this deduplication only works within a single scan. If you run du separately on A and then separately on B, each invocation correctly reports 500MB for its own scope — there's no way for the second invocation to know the first one already "spent" that data, because from either folder's own perspective, deleting it would indeed free that folder's contribution. The apparent disagreement is not an error; it's two different, both-correct answers to two different questions.

What good tool behaviour looks like

A storage tool aimed at helping you decide what to delete should, at minimum:

  • Not multiply-count the same inode more than once within a single combined scan total (the whole-disk or whole-folder number should reflect actual disk usage, not the sum of every path that points at it).
  • Make clear, when it does show a per-folder contribution, that the number represents "how much this folder's deletion would matter" rather than claiming to represent unique bytes on disk.
  • Ideally, flag when a file it's showing you has more than one hard link, since that context changes what deleting it will and won't accomplish.

Not every tool does all three. A simpler list-only tool might not track inodes at all, in which case its whole-disk total will run high on any Mac with meaningfully hard-linked content — which, outside of Time Machine-style backup structures, is relatively rare on an average user's home folder but common in specific development and backup contexts.

Where hard links actually show up on a typical Mac

Hard links are less common in everyday use than the amount of discussion they generate might suggest. On a typical single-user Mac without extensive backup software running, most files on disk have exactly one link — one name, one path, no ambiguity at all. The cases where hard links matter in practice tend to be specific: older-style local Time Machine backup structures that used hard links to represent unchanged files across snapshots without duplicating their data, some package formats that link shared internal resources, and certain developer tools that hard-link identical files across multiple project checkouts or package manager caches to save space (pnpm's content-addressable store is a modern example of this pattern, deliberately using hard links or reflinks to avoid storing the same package content once per project).

This means the double-counting problem is worth understanding conceptually even if it doesn't show up dramatically on every Mac. It matters most on machines with heavy use of tools that deliberately rely on hard linking to save space — ironically, the exact tools designed to reduce disk usage are also the ones most likely to expose a storage tool's hard-link handling as either correct or naive.

Reflinks and copy-on-write: a related but distinct case

APFS also supports a related mechanism called cloning, sometimes exposed as a "reflink," where copying a file with cp -c (or through Finder's duplicate function in many cases) creates a second file that initially shares the same underlying data blocks as the original, only diverging and consuming additional space once one copy is modified. This is different from a hard link — it produces two genuinely separate files, each independently deletable, rather than two names for one file — but it creates a similar accounting puzzle: two files that appear to each be, say, 500MB, while together occupying only 500MB on disk until they diverge.

A thorough storage tool ideally accounts for this too, though it's a subtler case than classic hard links, since cloned files are less commonly surfaced as a specific concept by tools focused primarily on hard-link deduplication. If your combined totals still look inflated after ruling out hard links specifically, cloned files sharing storage are a reasonable next thing to consider.

How to test this yourself

You can construct a simple, safe test. In a scratch folder:

mkdir -p /tmp/hardlink-test
dd if=/dev/zero of=/tmp/hardlink-test/original bs=1m count=100
ln /tmp/hardlink-test/original /tmp/hardlink-test/linked-copy
du -sh /tmp/hardlink-test

You created a 100MB file and a hard link to it, so the folder contains two names for the same 100MB — not 200MB. A du -sh on that folder should report roughly 100MB, not 200MB, confirming its inode-deduplication behaviour. Point any GUI storage tool at the same folder and compare its reported total to see whether it does the same thing. Clean up afterwards with rm -rf /tmp/hardlink-test.

Where VolumeLens fits

VolumeLens counts each hard-linked inode once in its combined totals, specifically to avoid reporting a bigger number than your disk actually shows as used. This is one of the guarantees we hold the app to, because a storage tool whose grand total doesn't reconcile with df -h erodes the trust the whole category depends on. If you want to see how the scan handles cases like this in your own environment, the free tier lets you scan, browse, and check the numbers yourself — no account needed. Take a look at how it works or download VolumeLens to run the test above against your own disk.