Let's get back to top-level directories. We'll discuss /bin/, /sbin/, and /usr/ first, because they are really similar. As stated in the overview, all of these directories contain binaries used by normal users and administrators of the system. Let's see where those binaries are and how our user session knows how to find them in the process. We'll manage this by using the echo command. Its short description is simply display a line of text. Let's see how it works:
reader@ubuntu:~$ echo
reader@ubuntu:~$ echo 'Hello'
Hello
reader@ubuntu:~$
If we use echo without passing an argument, an empty line of text is displayed (pretty much just as promised by the short description!). If we pass text, which we enclose in single quotes, that text is printed instead. In this context, a bit of text which contains either letters, numbers, or other characters is referred to as a string. So, any string we pass to echo will be printed in our Terminal. While this might not seem that interesting, it is interesting when you start to consider variables. A variable is a string which value is, as the name implies, variable from time to time. Let's use echo to print the current value of the variable BASH_VERSION:
reader@ubuntu:~$ echo BASH_VERSION
BASH_VERSION
reader@ubuntu:~$ echo $BASH_VERSION
4.4.19(1)-release
reader@ubuntu:~$
You should notice we did not use the echo BASH_VERSION command, since that would print the literal text BASH_VERSION, but we instead started the variable name with a $. In Bash, the $ denotes the fact that we're using a variable (we will explain variables and variable interpolation further in Chapter 8, Variables and User Input). Why are we telling you this? Because the binaries we can use from our Terminal are found by using a variable, specifically the PATH variable:
reader@ubuntu:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin <SNIPPED>
reader@ubuntu:~$
As you can see here, binaries need to be in the /usr/local/sbin/, /usr/local/bin/, /usr/sbin/, /usr/bin/, /sbin/, or /bin/ directory for us to be able to use them (with the current value of PATH, which we can change, but that's out of scope for now). That would mean that binaries we've been using up until now (cd, ls, pwd, and echo) would need to be in one of these directories so that we can use them, right? Unfortunately, this is where things get slightly complicated. On Linux, we basically use two types of binaries: those that are found on disk (in a directory as specified by the PATH variable), or they can be built into the shell we're using, then called a shell builtin. A good example is actually the echo command we just learned, which is both! We can see what type of command we're dealing with by using type:
reader@ubuntu:~$ type -a echo
echo is a shell builtin
echo is /bin/echo
reader@ubuntu:~$ type -a cd
cd is a shell builtin
reader@ubuntu:~$
If a command is both built-in and a binary within the PATH, the binary is used. If it is only present as a built-in, such as cd, the built-in is used. As a general rule, most commands you use will be binaries on disk, as found in your PATH. Furthermore, most of these will be present in the /usr/bin/ directory (on our Ubuntu virtual machine, more than half of the total binaries are present in /usr/bin/!).
So, the overall goal of the binary directories should be clear: to provide us with the tools we need to perform our work. The question remains, why are there (at least) six different directories, and why are they divided between bin and sbin? The answer to the last part of the question is easy: bin has normal utilities used by users, while sbin has utilities used by system administrators. In that last category, tools related to disk maintenance, network configuration, and firewalling, for example, are found. The bin directories contain utilities that are used for filesystem operations (such as creating and removing files/directories), archiving, and listing information about the system, among others.
The difference between the top-level /(s)bin/ and /usr/(s)bin/ is a bit more vague. In general, the rule is that essential tools are found in /(s)bin, while system-specific binaries are placed in the /usr/(s)bin directories. So if you installed a package to run a web server, it would be placed in either /usr/bin/ or /usr/sbin/, since it is system-specific. Finally, the /usr/local/(s)bin/ directories are, in our experience, most often used for binaries that are installed manually, instead of from a package manager. But you could place them in either directory of the PATH to work; it's mostly a matter of convention.
As a final note, /usr/ contains more than just binaries. Among these are some libraries (which have the same relation to the /lib/ and /lib64/ top-level directories) and some miscellaneous files. If you're curious, we would definitely recommend checking out the rest of the /usr/ directory using cd and ls, but the most important thing to remember is that binaries and libraries can be located here.