Files#
The vocabulary of the filesystem. Every file is a typed entry in the tree, addressed by a path, dereferenced through links, and discovered through environment variables. The four sections below are the orientation an operator runs through before navigating or modifying the tree on an unfamiliar host.
File Types#
The first character of ls -l output identifies the type. Linux treats
files, directories, devices, kernel objects, and IPC endpoints as the same
kind of thing (paths in the tree), and this character is how the listing
tells them apart at a glance.
Char |
Type |
|---|---|
|
regular file |
|
directory |
|
symbolic link |
|
character device |
|
block device |
|
named pipe (FIFO) |
|
socket |
Example listing.
$ ls -l
total 4
-rwxr-xr-x 1 root root 1024 Jan 1 12:00 script.sh
drwxr-xr-x 2 root root 4096 Jan 1 12:00 dir
lrwxrwxrwx 1 root root 10 Jan 1 12:00 link -> script.sh
crw-rw-rw- 1 root root 1, 0 Jan 1 12:00 char
brw-rw---- 1 root disk 8, 0 Jan 1 12:00 block
prw-r--r-- 1 root root 1, 8 Jan 1 12:00 fifo
srw-rw-rw- 1 root root 1, 9 Jan 1 12:00 socket
Regular File -#
A byte sequence on disk (source code, binaries, images, logs, configs).
Created with touch, written by any process with write permission.
$ touch hello.txt
$ stat hello.txt | grep 'regular file'
Directory d#
A list of name-to-inode mappings. Reading a directory lists entries;
writing creates, renames, or removes them. Traversing a directory
(cd into it, or resolving any path through it) requires the
execute bit.
$ mkdir -p project/src
$ ls -ld project
Symbolic Link l#
A small file whose contents are another path. Resolved each time it
is accessed, so a dangling link points at nothing. Distinct from a
hard link (multiple directory entries pointing at one inode), which
shows up as a regular file in ls -l.
$ ln -s /usr/bin/python3 py
$ readlink py
Character Device c#
A device node read or written one byte (or one ioctl) at a time
(terminals, serial ports, /dev/null, /dev/random). The pair of
numbers in ls -l (1, 3 for /dev/null) is major, minor,
the kernel’s identifier for the driver and instance.
$ ls -l /dev/null /dev/tty /dev/urandom
Block Device b#
A device node addressed in fixed-size blocks (disks, partitions, loopback devices, LVM logical volumes). Filesystems live on top of block devices.
$ ls -l /dev/sda /dev/nvme0n1 2>/dev/null
$ lsblk
Named Pipe p (FIFO)#
A pipe with a path, so unrelated processes can rendezvous through it. A writer blocks until a reader opens it, and vice versa. Useful for ad-hoc inter-process communication (IPC) without sockets.
$ mkfifo /tmp/q
$ ( echo hello > /tmp/q ) &
$ cat /tmp/q
Socket s#
A bidirectional IPC endpoint with a path, a Unix-domain socket.
Used by daemons that talk to local clients (Docker’s
/var/run/docker.sock, systemd’s /run/systemd/private, X11’s
/tmp/.X11-unix/X0). Network sockets do not appear in the
filesystem; only Unix-domain ones do.
$ ss -lx | head
$ ls -l /var/run/docker.sock 2>/dev/null
Paths#
A path names a file by describing how to walk to it through the
directory tree. The kernel resolves it one component at a time.
Absolute paths start at /; relative paths start at the process’s
current working directory. Walking through any intermediate directory
requires execute (x) permission on that directory, otherwise
resolution fails with EACCES.
Form |
Meaning |
|---|---|
|
absolute, starts at |
|
relative, starts at |
|
explicitly relative to |
|
one level up, then into |
|
current user’s home ( |
|
named user’s home (resolved via |
|
|
|
current / parent directory entries |
|
jump to |
|
implementation-defined; Linux collapses to |
|
shell variable expansion before path resolution |
|
not a separator, a literal byte in the filename |
Linux paths use / as the only separator and may contain any byte
except \0 and / itself. Spaces, newlines, dashes, and shell
metacharacters are all legal in filenames. Quote variables and
prefer -- to terminate option parsing.
Limit |
Value (Linux, default) |
|---|---|
|
4096 bytes, maximum full-path length |
|
255 bytes, maximum single-component length |
|
40, max symlink hops before |
Example invocations.
$ pwd
$ readlink -f link
$ realpath -e some/relative/path
$ basename /etc/ssh/sshd_config
$ dirname /etc/ssh/sshd_config
$ echo ~operator
$ echo ~+ ~-
$ getconf PATH_MAX /
$ getconf NAME_MAX /
$ find . -name '* *' -print0 | xargs -0 ls -ld
Variables#
Environment variables that affect filesystem operations. Many shell habits
(cd -, looking up commands by name, finding the right config) come down
to whether one of these is exported correctly, and a missing or wrong value
usually shows up as a path that resolves somewhere unexpected.
Variable |
Purpose |
|---|---|
|
the current user’s home directory |
|
the current working directory |
|
the previous working directory (powers |
|
colon-separated search path for executables |
|
the user’s login shell |
|
the current user’s name |
|
locale; affects sort order, case-folding |
|
preferred temporary directory ( |
|
per-user config (default |
|
per-user cache (default |
|
per-user data (default |
|
per-user runtime ( |
Links#
Two flavors of links. Hard links share an inode, so they are indistinguishable from the file they reference. Symbolic links store a path string and are resolved on each access. Symlinks can cross filesystems and point at directories; hard links cannot do either.
$ ln -s /usr/bin/python3 /usr/local/bin/python
$ ln /etc/hosts /tmp/hosts.bak
Common Tasks#
The recipes the operator reaches for once on target, when the question is what type of file is this, where does it really resolve, and what does the link graph look like.
Identify a file’s type.
$ stat -c '%F %n' /etc/passwd /tmp /dev/null /var/run/docker.sock 2>/dev/null
$ file /usr/bin/ls /etc/hosts /dev/null
Resolve a path through every symlink.
$ readlink -f /usr/bin/python
$ realpath -e /etc/alternatives/editor
Find broken symlinks under a tree.
$ find / -xtype l 2>/dev/null
List all hard links to one inode.
$ stat -c '%i' /etc/hosts
$ find / -xdev -inum "$(stat -c '%i' /etc/hosts)" 2>/dev/null
Inspect Unix-domain sockets the operator can reach.
$ ss -lx
$ find / -type s 2>/dev/null
Walk every named pipe on disk.
$ find / -type p 2>/dev/null
References#
man 7 path_resolution(how the kernel walks paths).man 1 realpath,man 1 readlink,man 1 basename,man 1 dirname.man 3 getcwd,man 3 realpath.man 1 ln,man 2 link,man 2 symlink(link primitives).man 1 stat,man 1 file(typing a path).man 7 fifo,man 7 unix(FIFO and Unix-domain socket semantics).Permissions for the execute bit on directories that controls path traversal.
Linux for the command quick-reference.