Everything Is a File
paradigm Library and Archive → Data Processing
Categories: computer-sciencesystems-thinking
What It Brings
The master metaphor of Unix. Every resource in the system — hardware devices, network sockets, inter-process communication channels, and actual files on disk — is accessed through the same interface: a file descriptor that supports open, read, write, and close. The “file” (a named container of sequential bytes, borrowed from the office filing cabinet) became so dominant that it restructured how an entire operating system conceptualizes resources. Plan 9 later took the metaphor to its logical extreme: even the network and the window system are filesystems.
Key structural parallels:
- Uniform interface over heterogeneous resources — a filing cabinet imposes the same access pattern on every document inside it: open the drawer, find the folder, read the contents. Unix does the same with file descriptors. A program that reads from a file can read from a pipe, a terminal, or a network socket without changing its code. The metaphor converts the bewildering variety of I/O devices into a single abstraction, just as the filing cabinet converts the bewildering variety of office documents into uniform folders.
- Named paths as addresses — in a library or archive, every item
has a catalog location: a shelf, a drawer, a box number. Unix maps
this onto the hierarchical filesystem path.
/dev/sdanames a disk the same way/home/user/notes.txtnames a text file. The naming convention does not distinguish between “real” files and device pseudo-files; the namespace is flat in its semantics, even when the underlying reality is not. - Sequential access as the default — a file in an archive is read from beginning to end. Unix file descriptors default to sequential byte streams. This is a powerful simplification: it means that programs can be composed with pipes (one program’s output becomes another’s input) because everything flows in the same direction. The metaphor privileges linear reading over random access, which shaped the entire Unix pipeline philosophy.
- Permissions as access control — an archive has rules about who can view, modify, or remove documents. Unix maps this onto read/write/execute permission bits attached to every file descriptor. Because everything is a file, everything gets the same permission model — a device, a socket, and a text file all use the same rwx bits. The metaphor extends the librarian’s access control to the entire system.
Where It Breaks
- Files are passive; devices are active — a file in a cabinet sits
there until someone reads it. A network socket has data arriving
asynchronously; a terminal has a human typing unpredictably; a device
has interrupts, timing constraints, and state machines. The file
metaphor imposes a passive, pull-based model on resources that are
fundamentally active and push-based. This mismatch leaks through in
the form of
ioctl()— the escape hatch that lets programs do device-specific things that the file abstraction cannot express. Everyioctlcall is an admission that the metaphor has broken down. - Not everything is sequential bytes — the file metaphor assumes a stream of bytes, but a GPU has command queues, a sound card has sample rates, and a network interface has packet boundaries. Forcing these into a byte-stream abstraction either loses information (packet boundaries disappear in TCP sockets read as streams) or requires elaborate encoding schemes. The metaphor works beautifully for text; it struggles with structured, real-time, or multi-dimensional data.
- The namespace conflates identity with location — in a real archive, moving a document to a different shelf changes its address but not its identity. In Unix, renaming or moving a file changes its path, which is the only way most programs refer to it. File descriptors (the integer handles) do provide location-independent identity, but only within a single process. The metaphor provides no system-wide persistent identity for objects, only locations — which is why symlinks, hard links, and mount points create confusion that a real librarian would find absurd.
- The metaphor hides concurrency — a filing cabinet assumes one reader at a time, or at least that readers do not interfere with each other. Unix files can be read and written simultaneously by multiple processes with no built-in coordination. The file metaphor provides no vocabulary for concurrent access, which is why Unix needed to bolt on file locking as an afterthought — and why file locking on Unix remains notoriously unreliable.
- Plan 9 proved the limits — Plan 9 from Bell Labs pushed “everything is a file” to its logical conclusion, making the network, the window system, and even process state into synthetic filesystems. The result was elegant but never achieved mainstream adoption. The metaphor, taken to its extreme, produces a system that is conceptually pure but practically awkward for use cases that do not fit the sequential-bytes-in-a-namespace model.
Expressions
- “Everything is a file” — the canonical statement of Unix design philosophy, often the first thing taught in a systems programming course
- “It’s just a file descriptor” — reassurance that a complex resource (socket, pipe, device) can be treated with the same familiar read/write interface
- “/dev/null” — the file that discards everything written to it, perhaps the purest expression of the metaphor: even nothingness is a file
- “cat /proc/cpuinfo” — using file-reading tools to inspect system state, because the kernel exposes process and hardware information as synthetic files
- “Write to stdout, read from stdin” — the compositional principle that follows from everything-is-a-file: programs become filters in a pipeline because their I/O is just file descriptors
- “On Unix, everything is a file. On Windows, everything is a registry entry.” — the comparative quip highlighting how different master metaphors produce different system architectures
Origin Story
The “everything is a file” principle emerged from Ken Thompson and Dennis Ritchie’s design of Unix at Bell Labs in 1969-1971. The idea was not articulated as a grand philosophy at the time; it grew from practical engineering decisions. Thompson wanted a simple, uniform I/O interface, and the file abstraction — borrowed from the familiar concept of documents in a filing system — was the most natural fit.
The key innovation was the file descriptor: a small integer that serves
as an opaque handle to any I/O resource. By making devices appear as
special files in the /dev directory, Thompson and Ritchie ensured
that existing file-manipulation tools (cat, cp, redirections) would
automatically work with devices. This was a profound act of metaphorical
extension: the filing cabinet expanded to contain the entire machine.
Doug McIlroy’s pipes (1973) exploited the metaphor further: if program
output is a file and program input is a file, you can connect them.
Linux’s /proc filesystem (inspired by Plan 9) pushed the metaphor
into system introspection: process state, kernel parameters, and
hardware information all became readable as files.
The metaphor’s success is measured by its invisibility. Most programmers do not think of “everything is a file” as a metaphor at all — it is simply how operating systems work. That naturalization is the hallmark of a paradigm-level conceptual mapping.
References
- Ritchie, D. & Thompson, K. “The UNIX Time-Sharing System,” CACM 17(7), 1974 — the foundational paper describing the file abstraction
- Kernighan, B. & Pike, R. The Unix Programming Environment, Prentice-Hall, 1984 — the canonical exposition of Unix philosophy including the everything-is-a-file principle
- Pike, R. et al. “The Use of Name Spaces in Plan 9,” Operating Systems Review 27(2), 1993 — Plan 9’s extension of the metaphor to its logical conclusion
- Raymond, E.S. The Art of Unix Programming, Addison-Wesley, 2003 — extensive discussion of everything-is-a-file as a design principle