File system paths and navigation
The file system is the part of your operating system that organizes your data on storage devices like disk drives. It also provides the means for programs to open, read from, and write to files. When you use bash (or other shells) to open a file or run a program, bash interacts with the file system to get the data you asked for.
Linux (like Windows and macOS) uses a hierarchical file system based on directories (other systems call these folders). A directory is itself a file (managed by the system) which lists its contents with details such as file size and access permissions. This list can include other directories, allowing a directory to contain subdirectories to any depth you like.
Linux treats all files as sequences of bytes, and leaves the meaning of those bytes to individual programs. Any program can read or write any file (provided you have permission to do so!).
In particular, the file system doesn't use file extensions (like .txt) to control which programs can open a file. You'll still see these in file names so humans know what the file contains, and so certain programs can understand how to process the file.
File system paths
You identify files on your computer using a path to the file, which tells the file system how to find the file. There are two different kinds of paths: absolute paths and relative paths.
Absolute paths
Absolute paths specify a file or directory location starting from the
root directory. This directory is the top of the file system hierarchy
and is written with a forward slash ("/
"). Every file and directory
in the system is contained within this root directory.
All absolute paths begin with a forward slash, meaning "start at the root." The path then contains the names of directories, separated by slashes. This describes the directories you would enter as you move to the file. The final name in the path is the file or directory the path identifies. For example:
/usr/bin/date
means, "from the root directory enter the directoryusr
; then enter the directorybin
; then you'll find the filedate
(this is the program run by the date command)./home/re268
means, "from the root directory enter the directoryhome
; then you'll find the directoryre268
(my home directory).
Absolute paths do not change (unless you move the file), but can be quite long for files contained in many subdirectories. To save on typing, shells provide an alternative means to access "nearby" files.
The working directory and relative paths
As you work, your shell keeps track of your current working directory. Linux users often say they are "in" (or "working in") a directory while it is their working directory. It is very common for your shell prompt to include the name of the working directory. You can also ask the shell to print the (absolute) path of the working directory with the pwd command.
pwd
- print name of current/working directory
$ pwd [OPTION]...
Relative paths specify a file or directory location starting from the working directory (rather than the root directory). This lets you refer to files in the working directory by name alone, or to files in subdirectories starting from the working directory (instead of from "/").
Example: Working on a project in your home directory
As the semester progresses, I might organize my home directory by creating a
cosc051
directory, with subdirectories for each project. I might
open my reference solution to the first programming project (in
vim) using an absolute path.
$ vim /home/re268/cosc051/project1/main.cpp
If my home directory (/home/re268
) is my current working directory,
I could open the same file with a relative path:
$ pwd
/home/re268
$ vim cosc051/project1/main.cpp
The shell looks for cosc051
in my current working directory and
interprets the path from there.
I might also choose to change my working directory to project1
,
and use an even simpler relative path:
$ cd cosc051/project1
$ pwd
/home/re268/cosc051/project1
$ vim main.cpp
Every Linux directory contains two special directory names that can be used in relative paths:
- A single dot,
.
, which always means "the current directory" - A double dot,
..
, which always means "the parent of the current directory"
The single dot is useful for specifying that you mean a file in the current directory
and not a shell command. A common example of this is writing ./a.out
to
mean "in the current directory; the file a.out
."
The double dot is useful for relative paths that go "back" up the directory hierarchy
(and sometimes into a different branch). I could specify the home directory
/home/clay
while in my home directory using the relative path
../clay
, which means "go back to /home
, then into
the directory clay
.
Home directories
Each user of a Linux computer has a home directory where they can store their personal files and programs. By default, no other user can view or change files in your home directory. Your home directory is also the default working directory when you begin a shell session. Your home directory name is the same as your username, and is a subdirectory of /home.
You interact with files in your home directory often enough that bash provides a
special nickname for it. Any time you type a path beginning with a tilde
("~
"), bash understands it to mean "my home directory"
(this is called tilde expansion). You can use this to write relative paths
starting in your home directory even when your working directory is somewhere
else.
Warning: Tilde refers to the home directory of the user that types it
Bash understands the relative path ~/main.cpp
based on the user
who types it. It refers to a file in my home directory when I use it, and a
file in your home directory when you use it.
Bash provides a related shortcut for referring to the home directory of a
particular user. When you type a tilde followed by a username, bash understands
it as the home directory of that user. So ~re268/main.cpp
refers
to a file in my home directory no matter who types it.
Windows allows multiple root directories, distinguished by letter names
(C:\
typically contains Windows itself; N:\
might be a
network-mapped drive).
Linux always has a single logical root, even when files are spread over multiple physical drives. Windows also uses backslashes in paths while Linux uses forward slashes.
MacOS users will find Linux paths familiar. This is because macOS is a descendent of the BSD family of Unix - it's a cousin of Linux!
The Linux directory tree has many cryptic names and an odd structure (such as
the distinction betwen /bin
, /usr/bin
, and
/usr/local/bin
). This pattern is historical, and comes from the
early days of Unix when disk drives were too small to hold the entire operating
system and all user data.
If you are curious about the original meaning of these directories, you can
read about the hierarchy with man hier
(though this man page is
not installed on all Linux distributions)