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

d

directory

l

symbolic link

c

character device

b

block device

p

named pipe (FIFO)

s

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

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

/etc/hosts

absolute, starts at /

etc/hosts

relative, starts at $PWD

./script.sh

explicitly relative to $PWD

../sibling

one level up, then into sibling

~

current user’s home ($HOME)

~operator

named user’s home (resolved via passwd)

~+ / ~-

$PWD / $OLDPWD (Bash, Zsh)

. / ..

current / parent directory entries

cd -

jump to $OLDPWD

//foo (leading //)

implementation-defined; Linux collapses to /foo

$VAR / ${VAR}

shell variable expansion before path resolution

\ (in a name)

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)

PATH_MAX

4096 bytes, maximum full-path length

NAME_MAX

255 bytes, maximum single-component length

SYMLINK_MAX (loop)

40, max symlink hops before ELOOP

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

$HOME

the current user’s home directory

$PWD

the current working directory

$OLDPWD

the previous working directory (powers cd -)

$PATH

colon-separated search path for executables

$SHELL

the user’s login shell

$USER

the current user’s name

$LANG / $LC_*

locale; affects sort order, case-folding

$TMPDIR

preferred temporary directory (/tmp if unset)

$XDG_CONFIG_HOME

per-user config (default ~/.config)

$XDG_CACHE_HOME

per-user cache (default ~/.cache)

$XDG_DATA_HOME

per-user data (default ~/.local/share)

$XDG_RUNTIME_DIR

per-user runtime (/run/user/<uid>)

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.

  • POSIX Pathname Resolution

  • Filesystem Hierarchy Standard