"Everything is a file" is slogan, so to say. A meme, if you will. It's not exactly true.
Obviously hardware devices are not actual files in the same way as a hello.txt
on an ext4 filesystem would be. Many of them don't even have anything to do with storage devices.
But even though not everything is a file, a number of things can be accessed as if they were files, at least somewhat. That is, they have a name in the filesystem tree, and the read()
and write()
system calls can be used for them. The latter is especially important if we consider the sense that "everything is a byte stream", since those calls access byte streams.
Since the same system calls work for regular files, raw disk devices, terminals, network sockets and pipes, the same set of tools can be used with each. E.g. echo foo
works the same regardless of where the output is connected. That can simplify the utility implementations, and makes it easier to apply them for new purposes. A shell or another command line utility does not need to do anything special to be connected through a pipe or a socket to an SSH server and accessed over the network. (Though for interactive sessions, SSH creates a pseudo-terminal, so it's not that different from a local session.)
Also, when a number of things have presence in the filesystem, they can be listed with ls
and accessed with cat
and shell redirections (echo foo > ...
). This can be useful for accessing special files in /proc
or /sys
from scripts, without needing a special binary to make a less-common system call.
Still not everything is a file, or a stream of bytes, and for things that are, not everything can be done with read()
and write()
. UDP sockets are not byte streams, as they transmit multi-byte datagrams with fixed sizes. (Though read()
and write()
still work on them, just a bit differently.) Some actions still need to be done with the ioctl()
system call, and the ioctl operations are device-specific. On Linux, network devices don't have names in the filesystem.
See also e.g.