13

It would seem that if a file does 'everything', then it's not in fact doing 'one thing'.

Sources:

How does 'everything is a file' not contradict 'do one thing and do it well'?

3
  • 21
    “Do one thing and do it well” is a design guideline for utility programs. The concept of a file is not a utility program. Commented Apr 6 at 13:43
  • 2
    Hi, stickynotememo. The post title should summarize the question. The post body should also contain the question and supporting research. I took the liberty to add sources to your post. If you feel this isn't in line with what you were asking about, you can revert this change. If you do revert my edit, please clarify your post. Commented Apr 6 at 15:32
  • 2
    I don't understand how you get "a file does everything" from "everything is a file". Files don't do anything; files are what get things done to them. Commented Apr 8 at 14:04

5 Answers 5

19

Not only there is no contradiction—both go the same way.

“Do one thing and do it well” encourages composition over monolith. For instance, instead of having one huge application that makes it possible to create videos and also encode them and handle all sort of video devices such as video cameras, one could have a GUI for creating videos, and this GUI will rely on a separate program that deals exclusively with video encoding, and a separate program that handles devices and presents a video camera as a stream—in other words, a file.

The benefits of such an approach:

  1. Programs are smaller, and therefore easier to maintain.

  2. A user may only be interested in video encoding. No need to install the whole monolith just to do that.

  3. Parts of the system can easily be swapped, and alternatives can be created more easily than when trying to create the whole monolith.

“Everything is a file” is a convenient way to achieve “do one thing and do it well.” Think of it as a standard.

Consider electricity at home. In your country, there is very likely a standard for wall sockets. Where there is a socket, you can plug in your PC, or a phone charger, or a desk lamp, or a vacuum cleaner.

Does the fact that one socket supports all those appliances mean that it's doing too many things? Well, not really. It does one and one only thing: it powers stuff you plug in to it. If there were separate plugs for vacuum cleaners (preferably each manufacturer would have its own “standard”) and other ones for your PC (Dell PC plugs won't fit in sockets designed for HP!) and different ones for chargers, and then there would be ones for CFL and ones for Osram LEDs, and ones for Philips LEDs... each socket won't do less compared to a standardized one. It would have the exact same role.

Same here. A file is just a standard by which components of a system may interoperate.

3
  • 15
    In reality this approach falls apart a lot which is why we ended up with a mix of special APIs, ioctls and strange behaviours around that on Linux. Which - exactly - why the "everything is a file" approach of stuffing everything into that presentation model doesn't fit "do one thing well" approach and very well demonstrates all the ways overloading a single concept with too much work ends up generating unnecessary complexity. It's a great learning tool because of that :) Commented Apr 6 at 19:04
  • 1
    When the plan 9 people reflected on the UNIX principles, they admitted that “everything is a file” is a misconception and proposed the alternative “everything uses the file system interface”. I can’t find the actual quote, but plan9.io/sys/doc/9.html and plan9.io/sys/doc/names.html include some details Commented Apr 8 at 7:46
  • @sakisk if you were modelling it in Java, you'd have interface File, and there would be a whole lot of extends File. I'd call that "everything is a file" Commented Apr 10 at 12:03
12

Everything isn't a file. Everything exposes an interface that works as if it was a file.

So all the bits "do one thing well" but they all can be used the same way. A bit like all the tools in your tool box having handles that work with human hands, even though the business end is different.

4
  • Related philosophy: Everything is a number But now you've got me feeling shy about exposing my interface. Commented Apr 6 at 16:01
  • 1
    @candied_orange Everything is most definitely a lambda. LOL Commented Apr 6 at 20:08
  • @Basilevs Lambda: The Ultimate Operating System Commented Apr 7 at 14:37
  • @Basilevs well yes, but of course lambdas are also Turing machines, and Turing machines are numbers, so the Pythagoreans were right. Commented Apr 8 at 17:03
4

Because Unix Philosophy is more like guidelines than actual rules. I think you are correct to see the contradiction. Both rules, put into absolutes would conflict.

A file stream is a pretty bad abstraction for a network socket, but it allows programs made for reading normal files to "just work" on network sockets ("Everything is a file" wins over "Do one thing well"). Admittedly it works well enough in most cases. For an OS that took "Everything is a file" even futher than Linux, check out Plan 9

For an opposite example, "SQLite" exposes its API as an internal library calls, not as some kind of virtual file system. ("Do one thing well" wins over "Everything is a file"). That is because a fully-capable SQlite virtual FS would be insane, although there are limited variations such as sqlitefs.

3

The principle that "everything is a file" is an abstraction that shields programs from specific hardware. This abstraction is the very thing that permits programs to focus on their job. No matter where the data comes from — a "real" file on disk, output from another program, from the terminal, the serial bus, or from a network connection: The program is shielded from it. In its simplest form it can simply read a byte stream from stdin and write the result to stdout, i.e., use regular file descriptors for its data that are already open and ready to use. It does not have to know anything about anything except the data logic. The result is a tool that is highly portable across a universe of devices: Your toaster, an IBM mainframe, some AWS instance or your smartphone. You don't have to change a single line of code. The power and benefit of this concept is immeasurable.

In a different world where all the data sources and -destinations needed to be treated specifically, a large portion of any utility like grep, cat, sed etc. would have to be concerned with operating system APIs and periphery handling unrelated to their actual task.1

The perspective of the operating system whose job it is to give user space programs access to the periphery is also interesting: Even though it must do a myriad of jobs and must often have detailed hardware knowledge it manages to make it look like one job, which is exactly what makes life so easy for the user space programs.


1 Actual reality, of course, is a bit messier: Mostly for convenience and improved usability, many programs in fact do distinguish between different data sources or destinations. For example, many programs are able to open named files or behave differently when they detect that their input and output is a terminal (which in turn often creates problems e.g. in emulations!).

2
  • Nothing is "hardware" about files. Even "block device" is unrelated to hardware. At best, these are OS level concepts and even then, the claim is dubious. This is an interfaces provided by OS for user-space code. Commented Apr 8 at 12:52
  • @Basilevs This is exactly what I said, I'm glad we agree. Commented Apr 8 at 13:59
2

This is a false dichotomy. There are following options:

  • everything is a file
  • do one thing well
  • do not work at all on a general purpose OS.

File is an interface (one of) of an general purpose operating system that establishes a bridge between drivers (filesystems, IO devices, network) and user space programs (editors, messengers, music players).

It is a limited and arguably not very universal interface. Unix saying "everything is a file" is a lie, in a sense that operations that it allows to do over a file object are by no means file-like. Unix can send datagrams over file, listen for them, execute a broad set of esoteric commands like "write data and wait for an hardware interrupt".

Windows separates un-file-like operations better, by providing other types of OS handles (sockets, pipes, ports). It still gives some file-like operations to those though.

There is indeed an inherent contradiction between an attempt to implement generic interface for disparate entities and make it work well for a single task.

The current situation (Unix adding strange operations over files and Windows supplying some file-like operations on non-file devices) is the result of a compromise. Too narrow of interface would shift complexity from device driver to user space programs. Too wide interface would shift the complexity the other way. Imbalance would cause one or the other to die out. General purpose OS is tasked with balancing things out, hence suboptimal, but universal solutions.

To really understand how the conflict is resolved, one has to look into real-time or specialized or embedded OS implementations - there compromises are resolved in a different way because no priority is given to broad application of an OS.

7
  • 2
    I always interpreted "everything is a file" in Unix to mean "everything is treated as stream, which is often or almost always implemented as a file on disk." So, I'm not entirely sure what you mean by 'Unix saying "everything is a file" is a lie, in a sense that operations that it allows to do over a file object are by no means file-like.' In many ways, "file operations" in Unix are "stream operations", and vice-versa. Commented Apr 6 at 18:32
  • 3
    @GregBurghardt UDP and hardware do not have streams, yet are handled as files. Commented Apr 6 at 19:17
  • 5
    It's more about everything being accessible as a file, @GregBurghardt, ultimately. The end goal is that the file interface handles everything you would need to interact with; it does one thing ("file" I/O), but does it well enough that any conceivable task can be accomplished as a "file I/O" task. It doesn't quite live up to that in reality, but the intent is simply that you shouldn't need to expose or use any other sort of interface. Commented Apr 7 at 1:24
  • 1
    @GregBurghardt: I think it's more about "treat everything as a homogeneous sequence of bytes". Historically, it was not uncommon for file systems to use different abstractions, such as treating a file as a collection of records with a size that's hard-coded, fixed for an entire file when it's created, variable within a file but immutable for each record once written, or variable and mutable on a per-record basis. Unfortunately, data interchange between such systems and those where each file is a single stream of bytes was awkward. Commented Apr 7 at 21:44
  • I guess the "there is a filename" might also be part of it? Commented Apr 8 at 0:30

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.