Understanding the Bin, Sbin, Usr/bin, Usr/sbin Split (2010)
Key topics
The age-old debate about the `/bin`, `/sbin`, `/usr/bin`, and `/usr/sbin` directory split has resurfaced, with commenters diving into the historical context and questioning the relevance of these legacy structures in modern Linux distributions. While some argue that the traditional layout is maintained due to "historical reasons" and accumulated rules, others point out that some distros, like Arch Linux, have made efforts to simplify the directory structure. A lively discussion ensues, with some commenters poking fun at the complexity and others suggesting that new OS designs, like Google's Fuchsia, might offer a fresh start. As it turns out, some mainstream systems, like macOS, have inherited and adapted these directory structures, while others have started to simplify them, sparking a debate about the perfect balance between tradition and innovation.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
2h
Peak period
87
0-6h
Avg / period
13.7
Based on 123 loaded comments
Key moments
- 01Story posted
Jan 4, 2026 at 8:49 AM EST
3d ago
Step 01 - 02First comment
Jan 4, 2026 at 10:59 AM EST
2h after posting
Step 02 - 03Peak activity
87 comments in 0-6h
Hottest window of the conversation
Step 03 - 04Latest activity
Jan 7, 2026 at 11:15 AM EST
7h ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
> I'm surprised that, having something immutable, you'd choose to go the other direction.
I can somewhat imagine that having been limited by space and having to swap out disks all the time one would jump on the train of mutability without fully appreciating the benefits of immutability.
But then you get things like Esperanto. Esperanto takes about 1/4 of the time to learn compared to other languages. It’s taught in China and used as primary language in some settings. But, aside from a large number of people learning some Esperanto from Duolingo several years ago, it’s just another language now to have to learn.
Mac OS?
Nowadays most end users just use /usr/local or /opt/local or whatever is managed by Homebrew or Macports.
(FWIW, Fedora 17 was released in 2012.)
Edit: Oh haha, this article was posted 13 years ago and there was a similar thread which is how I dug up that link... https://news.ycombinator.com/item?id=5944594
same for /var/ or wherever you store your DB tables like MySQL.
Practically in this century if I was starting a new OS I would set it up like so:
/bin for all system binaries. Any binary from a package installed by the OS package manager lived here.
/lib same but for shared libraries
/var for variable data. This is where you would put things like your Postgres data files.
/tmp for temporary files.
/home as usual.
/dev as usual.
/boot as usual
/etc as usual
/usr would be what /usr/local is on most systems. So /usr/bin is binaries not installed by the OS package manager. /usr/etc is where you put config files for packages not installed by the package manager and so on.
Get rid of /usr/local and /sbin.
/media replaces /mnt entirely (or vice versa).
Ditch /opt and /srv
Add /sub for subsystems: container overlays should live here. This would allow the root user (or a docker group, etc.) to view the container file system, chroot into it, or run a container on it.
Then again, nobody gave me a PDP-11 to decide so my vote doesn’t count :)
This one never sat well with me. I think of /var as temporary data, something I can lose without much consequence. But never data files. I know it's the default, but still.
/srv I like because it seems like a proper place to separate server-related data, i.e. /srv/wwwroot or similar. But if you like /var, that of course would be the place for this type of data.
/var is data that needs to be writable (/usr/*, /bin and /lib may be readonly), and that might be important. Like databases, long-term caches, mail and printer queues, etc.
If a system is intended to serve data on a network (file shares, databases, websites, remote backups, etc), /srv is where the requisite data for those things should live. I think that's a good idea.
> This directory contains subdirectories which are used as mount points for removable media such as floppy disks, cdroms and zip disks. https://specifications.freedesktop.org/fhs/latest/media.html
/var is used for websites and databases, but defaults for most packages don't use /srv by default. (I have the feeling that /srv is relatively new.)
Along p_ing's lines I'd rename /var to something else, possibly not /srv because it's not just for servers, but it could be /data
My understanding is that sbin for system binaries, not necessarily statically linked. Normally /sbin is only in root's PATH, not normal user's. They are likely world executable, but in many cases you cannot actually run them as non-root since they usually touch things only root can access without special access (e.g. raw devices, privileged syscalls, /etc/shadow etc.). Not always though, like you can run /sbin/ifconfig as normal user in read-only mode.
* https://news.ycombinator.com/item?id=31338349
The 's' is for 'static' version of the explanation of the name of sbin is not actually supported by any 20th century Unix doco. The books on AT&T Unix System 5 (before which, things were in /etc) that actually give an explanation for sbin all say system binaries, or system administration commands; and none of them says anything about linkage.
The 'static link' story came from Linux people years afterwards. Here's Ian McCloghrie correcting this misconception in a Linux discussion back in 1993:
* https://groups.google.com/g/comp.os.linux.development/c/EKzL...
I pointed out the origins of sbin some years ago.
* https://lists.debian.org/debian-user/2019/02/msg00041.html
/usr/lib contents belongs in /lib if the contents is installed by the package manager. That way /usr/lib is what the user installed.
I think that became the rationale for /[s]bin vs. /usr/[s]bin (although based on the linked article, that may have been retconned a bit).
You were supposed to keep your root/boot filesystem very small and mostly read-only outside major updates. That meant that you could boot to a small amount of utilities (e.g. fsck) that would let you repair /usr or any other volume if it became corrupted.
I think the other poster is correct that stuff like fsck is supposed to go into /sbin because it is a "system" binary (but also statically linked since /usr/lib isn't mounted yet) and doesn't make sense to have in user $PATHs since nobody other than root should really be running that one.
Regardless, this is all deeply meaningless these days, particularly if you are running "ephemeral" infrastructure where if anything goes that wrong you just repave it all and start over.
> Ditch /opt and /srv
No. Chesterton's Fence, etc.
Since Linux has no concept of a base system, it's a stand-alone kernel with a hodgepodge of crap around it - this distinction makes no sense on Linux.
/opt is generally for software distros for which you don't have source; only binaries. Like commercial software packages. More common on Real UNIX(R) because most Linux users outside enterprise aren't running commercial software. You're putting your $500k EDA software under /opt.
The Linux base system is managed by the package manager, leaving local for the sysadmin to `make install` into
There is no such thing as a Linux base system.
Separate components, separate people.
Hence the term Ganoo plus Leenox...
Every occasion I’ve seen GNU coreutils installed on BSD, it’s been outside of the base and thus installed outside of /bin. Eg /usr/local or /opt/homebrew
In most distributions yes, there is Linux and then there is userspace on top of it. What you call "base system" is actually part of userspace, which has nothing to do with Linux itself.
Steam says hi.
On Windows, a common Steam library exists in Program Files directory, therefore not user specific. On Linux, each user has a separate Steam installation and library. I'm not sure why there isn't a common Steam library on Linux, but /opt would be a good place for it.
No reason this can't be done on Linux but since NT's security model is more flexible it's a lot easier to do so on Windows. You'd need to add dedicated users. (Running a Steam daemon as root would probably cause an uproar.)
Developers who knowingly reduce or disable default Windows security settings should be censured. Because in 99% of cases it is due to ignorance or plain laziness.
It doesn't "reduce or disable default Windows security settings" in a meaningful way if you say to yourself "that folder effectively is in ProgramData, but spelled wrong".
You should never hardcode the path since it can and has moved around, though MS has implemented hard links to legacy paths because most developers are stupid and against persistent better advice do it anyway.
Steam was first released in 2003, three years later.
For 80% of grievances about Windows, there is likely a solution in place that no one knows about because they didn't read the documentation.
But Windows XP, which came out in 2001, inherited everything from Windows 2000 and more, and was used extensively for gaming.
They didn't stop advertising Win98 support until sometime in early 2007.
Granted, Steam back then was a different creature than Steam now.
[1] https://web.archive.org/web/20020605222619/http://www.steamp...
And it's the same permissions either way. This isn't about permissions, it's about where they put the folder.
The actual solution, which remains both compatible and consistent with the security model, is that you should have to be administrator and pass UAC to install a game, just like you do to install anything else.
That's a Linux-ism. Other *nix there is a lot more in /usr/local.
In reality /usr is similar to Windows' System32 directory on most Unicies.
/opt is really the only good place for Java and where I've been putting it for decades (old habits die hard).
See, you assume here that /usr/local/ makes any sense.
I use a versioned appdir prefix approach similar to GoboLinux. So for me, /usr/local never ever made any sense at all. Why should I adhere to it? I have ruby under e. g. /Programs/Ruby/4.0.0/. It would not matter in the slightest WHO would compile it, but IF I were to need to store that information, I would put that information under that directory too, perhaps in a file such as environment.md or some other file; and perhaps additionally into a global database if it were important to distinguish (but it is not). The problem here is that you do not challenge the notion whether /usr/local/ would make any sense to begin with.
> /opt is generally for software distros for which you don't have source; only binaries.
Makes no sense. It seems to be about as logical as the FHS "standard". Why would I need to use /opt/? If I install libreoffice or google chrome there under /opt, I can as well install it under e. g. /Programs/ or whatever hierarchy I use for versioned appdirs. Which I actually do. So why would I need /opt/ again?
You’re presenting your comment as a rebuttal but you’re actually arguing something completely different to the OP.
They’re talking about UNIX convention from a historic perspective. Whereas you’re talking about your own opinions about what would make sense if we were to design the file system hierarchy today.
I don’t disagree with your general points, but it also doesn’t mean that the OP is incorrect either.
* e.g. exempli gratia (or, in Spanish, ejemplo gratis)
* i.e. id est (literally means "that is")
The ports tree will still be very different from base, but I feel this may erode some of the difference between FreeBSD and a typical Linux distro in terms of user experience, with respect to base vs ports. You'll update both with pkg.
It is open-source, and I can get source files, but it’s precompiled…
"some" is an understatement.
The BSD ports explanation is a bit revisionist I hate to say, this all predates ports.
Good grief. How does this end up as the top comment on HN of all places? I'll bet anything that this author also thinks that systemd is way too opinionated and unified and that the system needs a less coupled set of init code.
1. The history of /usr subdirectories is a lot more complex than that. There was a /usr/lbin once, for example.
1. /usr/local is not where third party softwares from packages/ports go on "the BSDs". On NetBSD, they go in /usr/pkg instead, again exemplifying that this is quite complex through history and across operating systems.
Latter, if desired, the system, could override those libraries with another ones (newer compatible or patched), more thinking is needed about this. The key, from the process point of view, would to limit the access of such process to their own directories and some very limited system only local services by default,
And to extend this permissions, each binary in such directory would need to be in companion of a permissions request file that would require the approbation from the user or the system defaults patterns (each distro would have a point of view I guess), in the aim of improve process isolation and system, drivers, services access permissions.
This would need also restructure the console philosophy, how can manage the processes, and so on, that would need a big restructuration.
I mean, anyway people is duplicating space with containers trying to isolate process, remark in trying.
I know this is unrealistic due the deep change it would suppose, so consider I'm just thinking out loud.
PS: If you answer it already exists with AppArmor, SELinux, etc, then you did not understood the root of the issue with such modules.
So the /bin /sbin became redundant.
Sometime around 2020 someone observed that no current Linux can boot without /usr anyway. So what did they do? Move everything from /usr to / and drop the whole /usr legacy? Noooo, that would be too simple. Move / to /usr. And because that is still too simple, also move /bin, /sbin and /usr/sbin to /usr/bin, and then keep symlinks at the old locations because who's gonna fix hardcoded paths in 99% of all Linux apps anyway??
Oh, how I wish I was born in the '60s, when the world was still sane.
It's a lot simpler to merge them in a directory that can be mounted across multiple machines than have four separate mountpoints.
Nearly every shell script starts with "#!/bin/sh", so you can't drop /bin. Similarly, nearly every python script starts with "#!/usr/bin/env python", so you can't drop /usr/bin.
Hence symlink.
> Improved compatibility [...] That means scripts/programs written for other Unixes or other Linuxes and ported to your distribution will no longer need fixing for the file system paths of the binaries called, which is otherwise a major source of frustration. [..]
Scripts authors should use the binary name without a path and let the user's $PATH choose which binary to use and from where.
This union denies me the choice of using the statically linked busybox in /bin as a fallback if the "full" binaries in /usr are corrupted or segfaults after some library update.
> Improved compatibility with other Unixes (in particular Solaris) in appearance [...]
I don't care about appearances and I care even less about what Solaris looks like.
Did they take a survey of what Linux users care about, or just imposed their view on all of us because they simply know better? Or were paid to "know better" - I never exclude corruption.
> Improved compatibility with GNU build systems. The biggest part of Linux software is built with GNU autoconf/automake (i.e. GNU autotools), which are unaware of the Linux-specific /usr split.
Yeah, right. Please explain to me how GNU, the userspace of 99% of all Linux distributions isn't aware of Linux-specific /usr split.
And how is this any different from #1 ?
> Improved compatibility with current upstream development
AKA devs decided and users' opinion is irrelevant. This explains why GNU isn't aware of Linux /usr split - they simply don't want to be aware.
busybox in Alpine Linux has for example `ps` builtin. If you install ps with `apk add ps` to get the full version, it will remove the symlink for /bin/ps and replace it with the one you installed.
You need to read up on the purpose of busybox. It is not something that the kernel people has decided upon. It is an initiative of an group of people who needed some tools onto a single floppy.
/bin/ps on a Debian distro is 154522 bytes. The whole busybox in Alpine Linux is 804616 bytes and contains a whole lot more than just ps.
https://en.wikipedia.org/wiki/BusyBox https://busybox.net/
> merge-usr is a script which may be used to migrate a system from the legacy "split-usr" layout to the newer "merged-usr" layout as well as the "sbin merge".
> It is required for systemd ≥255 due to changes upstream, but it remains optional for other init systems.
As one who was, I find it makes the current world even harder to accept. Be careful what you wish for.
The tale that things were simple until they went to pot in 2000 is wholly ahistoric.
We'll skip PDP-7 UNIX, no hierarchical file system yet.
UNIX v1 on the PDP-11 had an RF11 fixed head disk (1mb) for / and swap, and an RK05 moving head disk (2.5mb) for /usr (the user directories)
By v2 they had added a second RK05 at /sys for things like the kernel, manual pages, and system language stuff like the c compiler and m6.
By v3 they added yet another RK05 at /crp for, well, all sorts of crap (literally), including yacc apparently. /usr/bin is mentioned here for the first time.
I don't feel like looking up when sbin was first introduced but it is not a Bell Labs thing. possibly BSD or AT&T UNIX? Binaries that one would normally not want to run were kept in /etc, which includes thing like init, mount, umount, getty, but also the second pass of the assembler (as2), or helpers like glob. Also i don't know when /home became canonical but at Bell Labs it was never a thing (plan 9 has user directories in /usr where they had always belonged logically).
The lib situation is more difficult. Looks like it started with /usr/lib. By v3 we find the equivalent directory as /lib, where it contains the two passes of the C compiler (no optimization pass back then), C runtime and lib[abc].a (assembler, B, C libraries respectively). /usr/lib had been repurposed for non-object type libraries, think text-preparation and typesetting.
By v4 the system had escaped the labs (see the recent news) and at that point everyone modified the system to their taste anyway. Perhaps it should be noted that the v7 distribution (which is the first that is very clearly the ancestor of every modern UNIX) has no /usr/bin, only /bin. /lib and /usr/lib are split however.
These are just some rough notes and due to a lack of early material they're still not as accurate as i would like. Also UNIX ran on more than one machine even in the early days (the manuals mention the number of installations) so there must have been some variation anyway. Something I'd like to know in particular is when and where RP03 disk drives were used. These are pretty huge in comparison to the cute RK05s.
I am also totally adding a /crp directory to my next system.
Doesn't being under $HOME make .local redundant? I guess one could argue for binaries going in an architecture-specific subdirectory if $HOME was on a shared filesystem, but that's not what's being done here.
To me, $HOME/.local/share and its siblings have always felt like a needless level of indirection, forcing me to jump through an extra hoop every time I want to access what's in there.
(I know it's possible to override it with an environment variable, but support for those overrides is spotty, and I think sensible defaults would be nicer.)
This would match the more recent $HOME/.var that's in widespread use via Flatpak.
So if that was their reasoning, it reinforces my view that they didn't think their design through very well.
It is Microsoft thing. You must pollute the user's /home as much as you can. Can i say that i have 3 daemons on my computer respobsible for ... credentials. This is the way to go.
I worked at an R&D center where we had hundreds of UNIX systems orf all types(i.e. Sun, Ultrix, HP, Symbolics, etc.) We also had Sun 2's , 3's and 4's - each with different CPU's/architectures and incompatible binaries. Some Suns had no disks at all. And with hundreds of systems, we literally had a hundred different servers across the entire site.
I would compile a program for a Sun 3, and needed a way to install the program once, for use on hundreds of computers. Also teams of people on dozens of different computers needed to share files with each other.
This was before SSH. We had to use NFS.
It was fairly seamless and .... interesting.
Later, I wrote code a university that had even more heterogeneous clusters.
The problem today is the siloification and bias against system diversity that doesn't account for proper software configuration management and support of multiple platforms. Portability is a dying art.
Slapping it down as "FHS is now a standard" does not change anything. People will ask why it is suddenly a standard when it hasn't made any sense at all whatsover. bin versus sbin is also pointless. Inertia is one primary reason why nobody fixes things usually.
Speaking of things which are needlessly complex, I'm reminded of this classic post on the tortured history of the browser User-Agent header:
https://webaim.org/blog/user-agent-string-history/
Highly recommended!
For me this was an eye-opener. I kept trying to wrap my head around all these different paths and "standards" because I thought it was correct and deliberately designed. Looking back through the history this doesn't seem to be the case; I feel much better for being confused by all the different PATH conventions and strict hierarchies.
This is a security threat, especially with SETUID programs. If you could change the library, you could install new code and gain privileged access.
This was why /usr/sbin was created - all of the programs there were compiled with static libraries.
[0]: https://www.psychologytoday.com/us/blog/thinking-makes-it-so...
https://joeldare.com/where-i-put-personal-binaries-in-macos
One of our devs was also a gimp contributor, and he dropped gimp into /usr/local and filled up the filesystem. And back then package managers didn't exist, so you had to read the makefile and hope you didn't remove anything that was shared
/opt/gimp or /usr/local/gimp.
Local because in some places they mounted an nfs share, and local was local to you.
Additional info: many rules from many places are now in force that maintain the historical structure.