Memra

Four routes to one file

◈ 9 cards

Absolute and relative pathnames for the same file from three vantage points, what `.`, `..` and `~` really are, and how to ask your own system for its filename limit.

One tree, no drive letters

Every file on a UNIX system hangs somewhere below a single root directory, written /. There are no drive letters. A second disk, a USB stick or a network share is mounted — attached to the one tree at some existing directory, its mount point — and from then on it is reached by an ordinary pathname. A user need never know which physical device holds a file, and that unified namespace is the whole benefit of mounting.

A pathname is the route through that tree. It comes in two flavours, and the exam wants you fluent in both.

  • An absolute pathname starts at the root: /home/ada/proj/a.c. It begins with /, and it means the same file no matter where you are standing when you type it.
  • A relative pathname starts at your present working directory — the directory the shell considers you to be in, printed by pwd. proj/a.c means "from here, go into proj, then take a.c". Change directory and the same string names a different file, or nothing at all.

Three names carry the tree's structure, and all three are real directory entries rather than shell tricks:

  • . is the directory itself.
  • .. is its parent. (In /, .. is / — the root is its own parent, which is what stops .. from walking off the top.)
  • ~ is not a directory entry. It is expanded by the shell to your home directory before the command ever runs, and ~ada expands to that user's home. A program that receives ~/proj as a literal argument gets a directory named ~, which almost certainly does not exist. That is the reason it must always be unquoted.

Worked example — one file, four pathnames, three vantage points

Ada's home is /home/ada and the file is /home/ada/proj/a.c. Start inside proj, and prove where you are standing before every claim:

$ pwd
/home/ada/proj
$ ls a.c                 # relative: from here
$ ls ./a.c               # the same, said explicitly
$ ls ../proj/a.c         # up to /home/ada, back down into proj
$ ls /home/ada/proj/a.c   # absolute: true from anywhere

All four name the same bytes. Now walk to the parent and re-check which of them still work:

$ cd ..
$ pwd
/home/ada
$ ls proj/a.c            # relative names shift with you
$ ls ~/proj/a.c          # the shell rewrites ~ to /home/ada
$ ls /home/ada/proj/a.c   # unchanged

And from somewhere else entirely:

$ cd /tmp
$ ls a.c                 # ls: cannot access 'a.c': No such file or directory
$ ls ~/proj/a.c          # still fine — ~ does not depend on where you are

The lesson is not that one form is better. It is that an absolute pathname names a file; a relative pathname names a file plus a place to stand from. When a script fails on somebody else's machine, a relative path that assumed a working directory is the first thing to suspect.

How long may a filename be?

The kernel allows almost any byte in a filename, but there is a length limit, and the limit is a property of the file system, not of the machine — one mounted file system may permit 255 bytes while another permits fewer. So the question "what is the maximum filename length on your system?" is only answerable about a particular place in the tree, and the command that answers it takes a pathname argument:

$ getconf NAME_MAX /
255
$ getconf NAME_MAX /tmp
255

Historically System V allowed 14 characters and BSD raised it to 255; Linux and the modern BSDs are all in the 255 camp, and that is what you will see. Do not confuse it with PATH_MAX, the limit on a whole pathname, which is typically 4096 — a filename of 255 bytes is legal in a path that is nonetheless too long to use.

/home/adahomeprojworking directorya.cthe targetb.cdocsplan.md
Standing in proj, the file a.c is reachable as a.c, ./a.c, ../proj/a.c, ~/proj/a.c and /home/ada/proj/a.c — five spellings, one inode.
NORMAL ~/memra/learn/comp-325/pathnames-and-navigating-the-tree utf-8 LF