Mac file system structure: two trees over one disk

A path that works in a terminal window and a path that appears in a Finder window are describing the same disk, and they do not look alike. Finder shows a startup disk named Macintosh HD holding four folders. The shell shows a root directory holding twenty two entries, several of which are symbolic links pointing somewhere else entirely. Neither view is wrong. They are two presentations layered over one storage device, and a good deal of confusion about where a file lives comes from switching between them without knowing which one is being read. Understanding the layout is not academic: it decides where scripts belong, which folders survive a macOS update, and why some writes fail no matter what privileges are attached to them.

Two views of the same disk

Apple built the difference in deliberately. The documentation for the platform states it plainly.

Users access the file system directly through the Finder, which presents a user-oriented view of the file system by hiding or renaming some files and directories. Apps access the file system using the system interfaces, which show the complete file system precisely as it appears on disk. Source: developer.apple.com

Running ls -la / on a current macOS install returns entries Finder never draws: bin, sbin, usr, opt, private, dev, cores. Three of those top level names are not directories at all. etc, tmp, and var are symbolic links pointing into private, kept at the root so that decades of Unix software written for other systems still finds what it expects.

Finder hides that entire layer because none of it is user content. The practical consequence is that a folder can be perfectly real, reachable, and writable, and still be invisible in every Finder window on the machine. When a build tool reports a file at /usr/local/share/something, searching Finder for it produces nothing, and the folder is exactly where the tool said it was.

Two habits close the gap. Command+Shift+G in any Finder window accepts a typed path and jumps to it, including into hidden directories. Command+Shift+Period toggles hidden items on and off for the current window. Neither changes anything on disk. They only widen what Finder is willing to draw.

The four domains, and which one a file belongs to

Above the directory names sits a simpler idea that explains most of them. macOS divides everything into four domains, separated by who the content is for rather than by what type of content it is.

Domain Where it lives Who can change it
User /Users/<name> that user
Local /Applications, /Library administrators of this Mac
Network mounted network volumes a network administrator
System /System nobody, including root

Apple describes the user domain as reflecting the home directory of whoever is logged in, the local domain as resources shared among all users of one computer, and the system domain as software installed by Apple that users cannot add to, remove, or alter.

The useful question when deciding where something goes is not what kind of file it is. It is who else needs it. A font one person uses goes in ~/Library/Fonts. A font every account on the machine needs goes in /Library/Fonts. A font that ships with macOS lives under /System/Library/Fonts and is not a place to add anything. Three folders with the same name, three different audiences, and the wrong choice produces a font that works for one login and vanishes at the next.

The same rule sorts applications, launch agents, preference files, and printer drivers. Almost every duplicated folder name in macOS is one concept repeated once per domain.

Reading the root directory one line at a time

Entry What it holds
/Applications apps for every user, plus Utilities
/Library support files shared by all users of this Mac
/System Apple's own software, sealed and read only
/Users one home directory per account, plus Shared
/Volumes mount points for external and network disks
/private etc, tmp, var, reachable through symbolic links at the root
/usr Unix tooling; /usr/local is the writable part
/opt where Homebrew installs on Apple silicon, under /opt/homebrew
/bin and /sbin core command line tools loaded before anything else

Two of these deserve attention because they behave unlike the rest. /Volumes is not storage. It is a folder of mount points, created and destroyed as disks appear and disappear, which is why a script that hard codes /Volumes/Backup breaks the moment a second disk with that name is attached and the system names it Backup 1.

/usr/local is the exception inside a directory that is otherwise off limits. It does not ship with macOS, it is created by whatever installs into it, and it survives system updates. That is why so much third party tooling lands there, and why a missing /usr/local/bin on a fresh machine is normal rather than a symptom.

The system half is read only, and sealed

Since macOS Catalina the startup disk has not been one volume. It is two, presented as one. Checking mount on a running machine shows the root filesystem mounted with the flags sealed, local, read-only, and a separate volume mounted at /System/Volumes/Data.

In macOS 10.15, Apple introduced the read-only system volume, a dedicated, isolated volume for system content. macOS 11 or later adds strong cryptographic protections to system content with a signed system volume (SSV). Source: support.apple.com

The seal is a cryptographic hash covering every byte of the system volume, verified at boot. This is the reason sudo cannot help with a write into /System. The failure is not a permission problem that more privilege would solve. The volume is verified content, and modifying it would invalidate the signature Apple computed at install time.

The two volumes are stitched together by firmlinks, and the stitch points are listed in a plain text file at /usr/share/firmlinks. Reading it shows /Applications, /Library, /Users, /Volumes, /opt, /private, and /usr/local all mapping across to the data volume. Every writable path on the startup disk is one of those entries or sits below one. Everything else is sealed.

This design has a quiet benefit. A macOS update replaces the system volume as a unit and leaves the data volume alone, which is why applications, home directories, and Homebrew installations survive updates that rewrite the operating system entirely.

Three Library folders doing three different jobs

The word Library appears at three levels, and the difference matters more than any other naming collision in macOS.

/System/Library belongs to the operating system and sits behind the seal described above. /Library at the root holds shared support files for the whole machine: fonts, launch daemons, preference panes, and anything installed for every account. ~/Library inside a home folder holds one person's application data, and it is where most day to day surprises live.

Apple hides ~/Library from Finder by default. Holding Option while opening the Go menu reveals the entry, and the folder is always reachable by typing the path into Command+Shift+G. It is not protected in the way /System is. It is hidden because casual editing of it breaks applications, and the contents are meant to be managed by software rather than by hand.

Backups are where the three levels most often get confused. Copying a home folder captures ~/Library and therefore application settings, mail, and message history. It does not capture anything in /Library, so shared fonts, VPN configuration profiles, and system wide launch daemons stay behind on the old machine. A migration that felt complete and then quietly lost half a font collection almost always crossed that line.

The startup disk is not where it looks like it is

One small detail confuses almost everyone the first time it is noticed. Listing /Volumes on a running Mac shows an entry named after the startup disk, usually Macintosh HD, and it is a symbolic link pointing at /. The startup disk is not mounted under /Volumes the way an external drive is. It is the root, and the entry exists so that a path written as /Volumes/Macintosh HD/Users/name resolves correctly even though nothing is really stored there.

The display name is also just a label. Renaming the startup disk in Disk Utility changes what Finder prints and what that symbolic link is called. It does not change /, and any script written against the root path keeps working. A script written against the display name does not.

Where applications actually keep your data

Sandboxed applications do not write into a home folder freely. Each one gets a container, and the path is ~/Library/Containers/<bundle identifier>/Data, with a directory tree inside that mirrors the home folder. An app that appears to save into Documents may be saving into its own container, and the file will be visible to that app and to nothing else.

Two more locations catch people out. Application support data that is not sandboxed lands in ~/Library/Application Support/<app name>, which is the first place to look when settings need to be copied to another machine. And iCloud Drive, which Finder presents as a top level sidebar item alongside the home folder, is really stored at ~/Library/Mobile Documents/com~apple~CloudDocs. Scripts that walk a home directory will find it there, under a name that looks nothing like the label on screen, and files inside it may be placeholders that have not been downloaded yet. Mobile devices reach the same storage through their own paths, which is worth knowing before a rule is written that assumes every file is local; the notes on working from iPhone and iPad cover what stays reachable when the Mac is closed.

Where to put your own work

What is being placed Where it belongs
documents, projects, code anywhere under the home folder
a personal script ~/bin, added to PATH
a tool every account needs /usr/local/bin
an app for one person ~/Applications
an app for everyone /Applications
an external or network disk mounted automatically under /Volumes

The one rule underneath that table is to stop fighting the domain boundaries. Work that belongs to a person goes under that person's home folder, where it is backed up, permitted by default, and untouched by system updates. Work that belongs to the machine goes in the local domain, where administrator rights are the deciding factor. Nothing belongs in the system domain, and an attempt to put something there is a signal that the layout was misread rather than that permissions need loosening.

Knowing the map also changes how a working session is arranged. A path that is obvious in a terminal window and invisible in a Finder window forces a translation step every time attention moves between them. Some people close that gap by keeping hidden files permanently visible; a file manager with a built-in terminal closes it by making the two views share one location, so the folder on screen and the working directory of the shell are never out of step. A comparison of the available options is the faster way to judge whether that is worth changing.

What to change first

Open a Finder window, press Command+Shift+Period, and look at the home folder with hidden items shown. The list that appears is the layer every script and installer has been writing to. Once that view feels normal, decide whether the terminal and the folder should keep living in separate windows, which is the question Atriens was built around.

Frequently asked questions

Why can files not be written to /System even with sudo?

The system volume is mounted read only and sealed with a cryptographic signature that covers every byte of its contents. Elevated privileges do not change that, because the restriction is not a permission check. Anything that needs to be added system wide belongs in /Library or /usr/local, both of which live on the writable data volume.

What is the difference between /Library and ~/Library?

/Library at the root of the disk holds support files shared by every account on the Mac, such as fonts and configuration profiles installed for everyone. ~/Library inside a home folder holds one person's application data and settings. Copying a home folder to a new machine carries the second one and leaves the first behind.

How do you open a hidden folder in Finder?

Press Command+Shift+G in any Finder window and type the path, which works for hidden directories such as ~/Library and /usr/local. Command+Shift+Period toggles hidden items on and off for the current window instead. Neither changes any file attribute on disk.

Where does iCloud Drive actually live on disk?

Finder shows iCloud Drive as its own sidebar item, but the storage is at ~/Library/Mobile Documents/com~apple~CloudDocs inside the home folder. Scripts that walk the home directory will encounter it there. Some entries may be placeholders for files that have not been downloaded to the Mac yet.

Why do external drives appear under /Volumes instead of on the disk?

/Volumes is a folder of mount points rather than storage, created as disks are attached and removed as they are ejected. If a second disk with a name already in use is connected, the system appends a number, so a script that hard codes a path there can quietly start writing to the wrong disk.

Back to all posts