Home » Why is Linux’s filesystem designed as a single directory tree?

Why is Linux’s filesystem designed as a single directory tree?


Since the Unix file system predates Windows by many years, one may re-phrase the question to “why does Windows use a separate designator for each device?”.

A hierarchical filesystem has the advantage that any file or directory can be found as a child of the root directory. If you need to move data to a new device or a network device, the location in the file system can stay the same and the application will not see the difference.

Suppose you have a system where the OS is static and there is an application that has high I/O requirements. You can mount /usr read-only and put /opt (if the app lives there) onto SSD drives. The filesystem hierarchy doesn’t change. Under Windows this is much more difficult, particularly with applications that insist on living under C:Program Files

This is partly for historical reasons, and partly because it makes more sense this way.


Multics was the first operating system to introduce the hierarchical file system as we know it today, with directories that can contain directories. Citing “A General-Purpose File System For Secondary Storage” by R.C. Daley and P.G. Neumann:

Section 2 of the paper presents the hierarchical structure of files, which permits flexible use of the system. This structure contains sufficient capabilities to assure versatility. (…)

For ease of understanding, the file structure may be thought of as a tree of files, some of which are directories. That is, with one exception, each file (e.g., each directory) finds itself directly pointed to by exactly one branch in exactly one directory. The exception is the root directory, or root, at the root of the tree. Although it is not explicitly pointed to from any directory, the root is implicitly pointed to by a fictitious branch which is known to the file system. (…)

At any one time, a user is considered to be operating in some one directory, called his working directory. He may access a file effectively pointed to by an entry in his working directory simply by specifying the entry name. More than one user may have the same working directory at one time.

As in many other aspects, Multics sought flexibility. Users can work in a subtree of the filesystem and ignore the rest, and still benefit from directories to organize their files. Directories were also used for access control — the READ attribute allowed users to list the files in a directory, and the EXECUTE attribute allowed users to access files in that directory (this, like many other features, lived on in unix).

Multics also followed the principle of having a single storage pool. The paper does not dwell on this aspect. A single storage pool was a good match with the hardware of the time: there were no removable storage devices, at least none that users would care about. Multics did have a separate backup storage pool, but this was transparent to users.


Unix took a lot of inspiration from Multics, but aimed at simplicity whereas Multics aimed at flexibility.

A single hierarchical filesystem suited Unix well. Like with Multics, storage pools were usually not relevant to users. However, there were removable devices, and Unix did expose them to users, via the mount and umount commands (reserved to the “super-user”, i.e. the administrator). In “The UNIX Time-Sharing System”, Dennis Ritchie and Ken Thompson explain:

Although the root of the file system is always stored on the same device, it is not necessary that the entire file system hierarchy reside on this device. There is a mount system request with two arguments: the name of an existing ordinary file, and the name of a special file whose associated storage volume (e.g., a disk pack) should have the structure of an independent file system containing its own directory hierarchy. The effect of mount is to cause references to the heretofore ordinary file to refer instead to the root directory of the file system on the removable volume. In effect, mount replaces a leaf of the hierarchy tree (the ordinary file) by a whole new subtree (the hierarchy stored on the removable volume). After the mount, there is virtually no distinction between files on the removable volume and those in the permanent file system. In our installation, for example, the root directory resides on a small partition of one of our disk drives, while the other drive, which contains the user’s files, is mounted by the system initialization sequence. A mountable file system is generated by writing on its corresponding special file. A utility program is available to create an empty file system, or one may simply copy an existing file system.

The hierarchical filesystem also has the advantage of concentrating the complexity of managing multiple storage devices into the kernel. This meant that the kernel was more complex, but all applications were simpler as a result. Since the kernel has to care about hardware devices but most applications don’t, this is a more natural design.


Windows traces its ancestry back to two lineages: VMS, an operating system originally designed for the VAX minicomputer, and CP/M, an operating system designed for early Intel microcomputers.

VMS had a distributed hierarchical filesystem, Files-11. In Files-11, the full path to a file contains a node name, an account designation on that node, a device name, a directory tree path, a file name, a file type and a version number. VMS had a powerful logical name feature allowing shortcuts to be defined to specific directories, so users would rarely have to care about a directory’s “real” location.

CP/M was designed for computers with 64kB of RAM and a floppy drive, so it went for simplicity. There were no directories, but a file reference could include a drive indication (A: or B:).

When MS-DOS 2.0 introduced directories, it did so with a syntax that was compatible with MS-DOS 1 which itself followed CP/M. So paths were rooted at a drive with a single-letter name. (Also, the slash character / was used in VMS and CP/M to start command line options, so a different character had to be used as a directory separator. This is why DOS and later Windows use backslash, though some internal components also support slash).

Windows retained compatibility with DOS and the VMS approach, so it kept the notion of drive letters even when they became less relevant. Today, under the hood, Windows uses UNC paths (originally developed by Microsoft and IBM for OS/2, of related ancestry). Although this is reserved for power users (probably due to the weight of history), Windows does allow mounting through reparse points.

There are no security concerns behind having a single directory tree.

The guys who designed Unix had a bunch of experience with operating systems that required users to know what physical device contained a given resource. Since part of the purpose of an operating system is to create an abstract machine on top of real hardware, they thought it much simpler to dispense with addressing resources by their physical location and decided to put everything into a single tree of names.

This is only one part of the genius behind the design of Unix.

Related Solutions

Joining bash arguments into single string with spaces

[*] I believe that this does what you want. It will put all the arguments in one string, separated by spaces, with single quotes around all: str="'$*'" $* produces all the scripts arguments separated by the first character of $IFS which, by default, is a space....

AddTransient, AddScoped and AddSingleton Services Differences

TL;DR Transient objects are always different; a new instance is provided to every controller and every service. Scoped objects are the same within a request, but different across different requests. Singleton objects are the same for every object and every...

How to download package not install it with apt-get command?

Use --download-only: sudo apt-get install --download-only pppoe This will download pppoe and any dependencies you need, and place them in /var/cache/apt/archives. That way a subsequent apt-get install pppoe will be able to complete without any extra downloads....

What defines the maximum size for a command single argument?

Answers Definitely not a bug. The parameter which defines the maximum size for one argument is MAX_ARG_STRLEN. There is no documentation for this parameter other than the comments in binfmts.h: /* * These are the maximum length and maximum number of strings...

Bulk rename, change prefix

I'd say the simplest it to just use the rename command which is common on many Linux distributions. There are two common versions of this command so check its man page to find which one you have: ## rename from Perl (common in Debian systems -- Ubuntu, Mint,...

Output from ls has newlines but displays on a single line. Why?

When you pipe the output, ls acts differently. This fact is hidden away in the info documentation: If standard output is a terminal, the output is in columns (sorted vertically) and control characters are output as question marks; otherwise, the output is...

mv: Move file only if destination does not exist

mv -vn file1 file2. This command will do what you want. You can skip -v if you want. -v makes it verbose - mv will tell you that it moved file if it moves it(useful, since there is possibility that file will not be moved) -n moves only if file2 does not exist....

Is it possible to store and query JSON in SQLite?

SQLite 3.9 introduced a new extension (JSON1) that allows you to easily work with JSON data . Also, it introduced support for indexes on expressions, which (in my understanding) should allow you to define indexes on your JSON data as well. PostgreSQL has some...

Combining tail && journalctl

You could use: journalctl -u service-name -f -f, --follow Show only the most recent journal entries, and continuously print new entries as they are appended to the journal. Here I've added "service-name" to distinguish this answer from others; you substitute...

how can shellshock be exploited over SSH?

One example where this can be exploited is on servers with an authorized_keys forced command. When adding an entry to ~/.ssh/authorized_keys, you can prefix the line with command="foo" to force foo to be run any time that ssh public key is used. With this...

Why doesn’t the tilde (~) expand inside double quotes?

The reason, because inside double quotes, tilde ~ has no special meaning, it's treated as literal. POSIX defines Double-Quotes as: Enclosing characters in double-quotes ( "" ) shall preserve the literal value of all characters within the double-quotes, with the...

What is GNU Info for?

GNU Info was designed to offer documentation that was comprehensive, hyperlinked, and possible to output to multiple formats. Man pages were available, and they were great at providing printed output. However, they were designed such that each man page had a...

Set systemd service to execute after fstab mount

a CIFS network location is mounted via /etc/fstab to /mnt/ on boot-up. No, it is not. Get this right, and the rest falls into place naturally. The mount is handled by a (generated) systemd mount unit that will be named something like mnt-wibble.mount. You can...

Merge two video clips into one, placing them next to each other

To be honest, using the accepted answer resulted in a lot of dropped frames for me. However, using the hstack filter_complex produced perfectly fluid output: ffmpeg -i left.mp4 -i right.mp4 -filter_complex hstack output.mp4 ffmpeg -i input1.mp4 -i input2.mp4...

How portable are /dev/stdin, /dev/stdout and /dev/stderr?

It's been available on Linux back into its prehistory. It is not POSIX, although many actual shells (including AT&T ksh and bash) will simulate it if it's not present in the OS; note that this simulation only works at the shell level (i.e. redirection or...

How can I increase the number of inodes in an ext4 filesystem?

It seems that you have a lot more files than normal expectation. I don't know whether there is a solution to change the inode table size dynamically. I'm afraid that you need to back-up your data, and create new filesystem, and restore your data. To create new...

Why doesn’t cp have a progress bar like wget?

The tradition in unix tools is to display messages only if something goes wrong. I think this is both for design and practical reasons. The design is intended to make it obvious when something goes wrong: you get an error message, and it's not drowned in...