The $PATH variable on Linux systems usually contains /bin, /usr/bin, and /usr/local/bin. All three of these directories have binary programs in them, and there are a lot of misconceptions on the web about the differences. (Just like the question of what is the difference between HTTP GET and POST). This article tries to explain this, based on my understanding and the Linux documentation. (In this article, we are talking about Linux, or more precisely, Unix systems)

TL;DR

These bin locations are just a few directories and are not fundamentally different. Which commands go where depends entirely on user and distro preferences. For example, some distributions use /bin as a symbolic link to -> /usr/bin. The [ command is placed under /usr/bin for Ubuntu and /bin for OS X.

But generally speaking, we think of these directories as being organized as follows.

  • /bin for system critical programs, such as ls and cat, the definition of “critical” varies from one distribution to another.
  • /usr/bin holds the distribution’s administrative programs, such as Ubuntu’s own md5sum, which is where the binary will be located.
  • /usr/local/bin for the user’s own programs, e.g. if you compile a gcc, then the gcc executable binary should be in this directory.
  • In addition, there are three corresponding directories /sbin /usr/sbin /usr/local/sbin that hold system administration programs, such as deluser chroot service.

Again, this is just a way of managing files, you can even put your own binary under $HOME/bin. Also, software installed by OS X with homebrew will be placed under /usr/local/Cellar and a symbolic link to the relevant bin directory will be created in /usr/local/bin, but under Ubuntu, it will be placed under /usr/bin.

A deeper understanding

Also, you need to know that / /usr /usr/local are prefixes, and after you compile a software, you have to execute . /configure --prefix=/usr/local and then make && make install. Then /usr/local will be the prefix, the library files will be under /usr/local/lib, the configuration files will be under /usr/local/etc, and the executable files (binary) will be under /usr/local/bin.

Then we look at how these prefixes are chosen. If you have compiled a system like FreeBSD, you will find that the system libraries, base tools and kernel for these systems are put into a set of code trees, and compiling this code, the kernel and core libraries and tools are done together, and these are considered part of the operating system. These core files, then, have the root directory as the prefix. so / is the prefix for all core operating system programs.

Adding new programs outside this core constitutes a distribution, and the programs added to this distribution use /usr as the prefix.

Once you have installed the distribution, you install applications outside the distribution, and those applications usually use /opt, /srv as prefixes.

But if you compile an application yourself from source code, those programs are compiled specifically to you, the Site, in which case the default prefix is /usr/local.

Some history

As you can see, different distributions will have different interpretations. So there is Filesystem Hierarchy Standard which wants to specify a standard for file hierarchy. (Actually, I don’t think this standard makes much sense; such a specification cannot be forced on all distributions).

Even though most people now think that these three directories mean what they say at the beginning of this article, the truth is that they were not created with this purpose in mind.

The truth is that when Ken Thompson and Dennis Ritchie created Unix in 1969, they used a PDP-11 with two RK05 disks, each of which was only 1.5M.

Later the system became bigger and bigger, one disk was not enough and a second disk was needed, so a second one was mounted, called /usr to put user files (imagine having two disks, one for the system and one for user data, very logical). Then the system directories, /bin, /sbin, lib … are copied to the new disk and read and write on the new disk.

Then they got a third disk (ahh!!) ) and mounted it under /home, moving only the user’s files over. This way, by mounting different disks in different places, the system could make use of all 3 disks.

Of course, they must have a rule: “When the system first starts, the first disk must have all the programs needed to mount the second disk to /usr, like mount. If mount is placed in /usr/bin/mount, you run into the problem of whether the chicken or the egg comes first.” Very reasonable.

The split between /bin and /usr/bin is artificial, and this implementation detail from 1970 has survived. Blame it on those who stick to the rules and don’t ask why.

One could argue that this split is “unnecessary” if there is enough disk space. But later, for various reasons, this “unnecessary” assumption was broken. One reason is that with the introduction of shared libraries (dynamic linking), /lib and /usr/bin had to match, which was not a problem before, because everything was statically linked.

Anyway, ever since these two directories existed, people started giving them meanings: / for upstream files, /usr for local content; later they evolved to / for official releases from AT&T, /usr for distribution content, then IBM AIX or Dec Ultrix, and /usr/local for their own local Then people decided that /usr/local wasn’t good enough for new packages, so they added /opt! and maybe /opt/local in the future.

There were later attempts to standardize them by organizations such as Filesystem Hierarchy Standard that we mentioned earlier, but they didn’t try to understand why in the first place would be like this ……