Run ls -l on a Mac and you will occasionally see an entry with an arrow in it, like latest -> v2.3.1. That is a symbolic link, and it is a genuinely different thing from a hard link, which looks like an ordinary file and behaves like one right up until you understand what an inode is. Mac users run into both: symlinks show up in Homebrew installs, developer tool chains, and /etc; hard links show up less often but quietly underpin things like Time Machine's old-style backups. Confusing the two leads to real mistakes, including believing you have freed space when you have not. Here is what each one is, what it costs in bytes, and how Finder's own "alias" fits into the picture as a third, unrelated mechanism.
What a symbolic link actually is
A symbolic link, or symlink, is a small, separate file. Its entire content is a text string: the path to whatever it points at. When a program opens latest, the filesystem reads that string, sees it says v2.3.1, and transparently redirects the request to v2.3.1 instead. The symlink itself has its own inode, its own permissions, and its own tiny footprint on disk — typically well under a kilobyte, since it only has to store a path.
Because a symlink is just a path reference, it does not care where its target lives. It can point across volumes, across external drives, even at a target that does not exist yet or has since been deleted (a "broken" symlink, which ls -l will still show you, arrow and all). It can also point at a directory, not just a file, which is why you can symlink an entire folder of Homebrew formulae into /usr/local/bin without duplicating anything.
What a hard link actually is
A hard link is a different mechanism entirely. Every file on disk is, underneath its name, an inode — a data structure holding the file's metadata and the location of its actual data blocks. The name you see in Finder is a directory entry that points at an inode. A hard link is simply a second directory entry pointing at that same inode. There is no "original" and "copy" once you have created one; both names are equally real, and the file's data continues to exist as long as at least one name (one directory entry) still refers to that inode.
This has a direct consequence for space accounting. Deleting one hard-linked name does not free any bytes, because the inode is still referenced by the other name. The data only disappears once the last link to it is removed. Tools that count naively by walking directories and summing file sizes will double-count a hard-linked file if they encounter it under two different names, which is why a storage tool that claims to be accurate needs to track inode numbers and count each one once, not once per name.
Why symlinks can do things hard links cannot
On APFS and HFS+, hard links are restricted in ways symlinks are not:
- A hard link must stay on the same volume as its target, because inode numbers are only meaningful within one filesystem. A symlink, being just a text path, can point at a target on a completely different volume, including an external or network one.
- Ordinary hard links to directories are not permitted on APFS or HFS+ (some Apple system code uses a specialised directory-hardlink mechanism internally, but that is not something regular tools or users create). Symlinks can point at directories freely.
- A hard link needs its target to already exist as a real inode at creation time. A symlink can be created pointing at a path that does not exist yet.
That asymmetry is why almost every developer-facing use of linking on a Mac — versioned tool installs, /etc/localtime, convenience shortcuts into deeply nested build output — uses a symlink rather than a hard link. Symlinks are more flexible with a real trade-off: if you move or delete the target, the symlink breaks, whereas a hard link's target cannot really be "moved away" from it, since both names are equally the file.
Finder aliases: a third, unrelated mechanism
macOS also has "aliases," created via Finder's Make Alias command, and it is worth being precise that this is neither a symlink nor a hard link. An alias file stores a path like a symlink does, but it also stores additional identifying information about the target — enough that Finder can often relocate the target even after it has been moved or renamed, something a plain symlink cannot do (a symlink only stores a path; move the target and the path is stale). An alias file is larger than a symlink, typically a few kilobytes rather than a few bytes, because it carries this extra bookkeeping. It also behaves differently to command-line tools: most Unix commands see an alias as an ordinary file, not as a link, and will not follow it the way they follow a symlink.
The storage math
This is the part that matters if you are trying to understand where your disk space actually went:
- A symlink costs almost nothing — a handful of bytes for the path string, occupying at most a small filesystem block.
- A hard link costs nothing additional — it is a second name for data that already exists, so creating one does not increase the space used on disk.
- A Finder alias costs a few kilobytes — more than a symlink, because of the extra tracking data, but still trivial next to a real file.
- The only thing that costs the full size is the actual data, which exists once per inode regardless of how many hard-linked names point at it.
The common mistake is assuming that because you see a file's full size listed twice under two different names, you have two files' worth of data. If those two names are hard links to one inode, you have one.
Checking what you are looking at
ls -l is the fastest way to tell a symlink from an ordinary file — a symlink's permissions column starts with l, and the arrow shows you the target. To check for hard links, stat on a file shows a link count; a count above 1 means other names point at the same inode. Neither command modifies anything, so they are safe to run on real data while you are trying to understand a folder's actual layout.
Conclusion
Symlinks, hard links, and Finder aliases solve overlapping problems in three different ways, and only one of them — the actual file data behind a hard link — carries real weight on disk. Everything else is bookkeeping measured in bytes, not gigabytes.
This distinction matters when you are trying to trust a storage tool's numbers rather than just its pretty chart. We built VolumeLens to count hard links once, by inode, rather than once per name it finds them under — so a folder full of hard-linked files does not inflate your total, and the numbers you see match what du and Finder would agree on if you added them up by hand.