Paths and Path Resolution
Context
Every file has an address, a line of text that names one exact spot in the filesystem tree, and the machine turns that address into a location by a single mechanical rule. The rule has a second input you never typed, the directory the command happened to run from, which is why the same text can land on two different files.
You write a path every time you load a training set, point a script at a saved model, tell a library where to cache a dataset it downloaded, or pass a filename as an argument on the command line. It is the single most repeated action in applied work, and it is invisible until it fails.
When it fails, it fails the same way every time, with the operating system reporting that no such file or directory exists, and that message is correct even when the file plainly exists, because the address you wrote pointed somewhere else. A script that reads a data file works from the project root and fails from inside the folder it lives in. A job that ran by hand every day breaks the moment a scheduler runs it, because the scheduler started somewhere else. The previous lesson built the tree and showed how it nests, this one is about naming a location inside it precisely enough that the machine agrees with you, and predicting, before you press Enter, exactly which file you are about to hit.
Goal
- Print your current location with
pwdand explain what the output means and why it is always absolute. - Write an absolute path that identifies any file from the root directory, and a relative path that reaches a target from where you stand.
- Apply the two-branch resolution rule to any path plus any working directory and compute the exact destination on paper.
- Construct relative paths with
.and..that climb and cross the tree, not only descend it. - Diagnose an "it worked here but not there" failure by identifying the working directory the command actually ran in.
- Decide which kind of path a situation calls for, and state what each choice costs.
Prerequisites
Neither is required and the lesson stands on its own. They are here if you would rather see the tree drawn before you walk it.
- YouTube - "Linux File System/Structure Explained!" (DorianDotSlash) - a visual mental model of the tree, the root, and where files live.
- GNU Bash Reference Manual - "Bourne Shell Builtins" - the
cdandpwdentries, for the precise definition of each.
Table of Contents
- Path
- The Working Directory
- Absolute and Relative Paths
- Path Resolution: The Rule
- Working-Directory Sensitivity
Theory
SETUP - DO THIS FIRST (everything below depends on it):
Every block in this lesson walks the same small tree. Build it once now, and each path below resolves to a file that is really there.
mkdir -p ~/datasets ~/project/data # '-p' builds every missing level in one call
# the dataset the path examples name
echo "sepal_length,sepal_width,label" > ~/datasets/iris.csv
# a script one level above the data
echo "print('training')" > ~/project/train.py
# the file the resolution examples read
echo "epoch,loss" > ~/project/data/records.csv
echo "module 0 notes" > ~/notes.txt # sits in home, two levels above project/data
cd ~ # start every block below from your home directoryPath
What. A path is a text string that names the location of a file or directory inside the filesystem tree. It is the address you hand to the operating system so it can find one exact spot among millions.
Why. A program cannot act on a file it cannot locate. When you load a dataset, save a trained model, or read a config, you pass a path. Get it wrong and the OS reports "No such file or directory", the single most common beginner error. A path is the bridge between a name in your head and a byte sequence on disk.
When. Every time a file is referenced, opening, reading, writing, copying, deleting. There is no file operation without a path, explicit or implied.
A path is built from directory names joined by the forward slash /. A leading / is the root directory, the top of the tree, and every / after it steps one level deeper, into the name that follows.
# A path naming a dataset file, read left to right:
# / -> root directory (top of the tree)
# home/ -> the directory holding user folders
# goku/ -> this user's personal folder
# datasets/ -> a folder inside it
# iris.csv -> the actual file
/home/goku/datasets/iris.csvThis string is a route through the tree: start at root, step into home, then goku, then datasets, and there sits iris.csv. Each segment between slashes is one node.
# The same idea for a directory instead of a file, no extension needed:
/home/goku/datasetsA path ending at a directory looks identical to one ending at a file. The OS knows which is which by what actually lives there, not by the text.
DON'T:
- DON'T write paths with backslashes
\, that is Windows Command Prompt style. In the shell and in WSL the separator is always the forward slash. - DON'T put spaces around the slashes (
/home / goku), the path is one unbroken string.
The Working Directory
What. The working directory is the single directory your shell is standing in right now. It is an invisible argument silently handed to every path that does not start with /, and you never type it.
Why. Because it is invisible, it is the input people forget exists. A command finds a file one moment and fails the next, and the only thing that changed was this hidden input. Naming it and watching it is how you stop being surprised. It is also what lets you type a short filename instead of retyping a full address every time.
When. It matters on every path that is not anchored at root, and it changes every time you run cd. Whenever a path-based command behaves differently than expected, this is the first thing to check.
pwd prints the current value as one line that always begins with /, which is what makes it trustworthy for orientation, and cd is the command whose job is to move it.
# Ask the shell where it is standing, then move and ask again.
pwd # /home/goku
cd datasets
pwd # /home/goku/datasetsAfter cd datasets the shell steps one level deeper. Nothing on disk changed, only your vantage point. cd walks you to a different room, it never moves the furniture.
ls # iris.csvPairing pwd, where am I, with ls, what is around me, is how you orient yourself before doing anything that creates, overwrites or deletes.
The shell in a new terminal window does not start at root, it starts in the home directory, the personal folder assigned to your user account. On Linux and WSL that is typically /home/goku, on macOS /Users/goku. It is the one location you can always return to, and the shell gives it a shortcut, the tilde ~. VS Code's built-in terminal is the exception, it opens in the folder VS Code has open, ~/dev/bootcamp in this bootcamp.
# All three land in the same place.
cd ~ # tilde expands to the home path
cd # bare 'cd' defaults to home
cd /home/goku # the explicit absolute path# The HOME variable stores the same path that '~' expands to.
echo $HOME # /home/goku~ is built from $HOME, a value the OS sets when you log in. Seeing them match confirms the shortcut and the variable point to one place.
DON'T:
- DON'T assume you know your working directory, verify with
pwd. Assumptions here cause "file not found" and accidental overwrites. - DON'T treat the working directory as fixed for a session, any
cd, a bare one included, changes it underneath you. - DON'T put a space after the tilde (
~ /datasets), write~/datasets, or the shell reads them as two separate things.
Absolute and Relative Paths
What. An absolute path starts at the root directory / and spells out every step down to the target. A relative path does not start with / and describes how to reach a target from where you already stand. The presence or absence of that one leading character is the entire distinction.
Why. An absolute path means the same thing from anywhere, which removes all ambiguity in scripts, scheduled jobs and config files where the working directory is unpredictable. A relative path is short and survives moving an entire project elsewhere, because it records a relationship between files rather than a fixed spot.
When. Reach for absolute when correctness must not depend on your current location. Reach for relative for everyday navigation and for references inside a project whose files keep a fixed relationship to each other.
# Absolute: starts at root, works identically from anywhere.
cat /home/goku/datasets/iris.csv
cd /tmp
cat /home/goku/datasets/iris.csv # same file, the 'cd' changed nothingThe leading slash is what guarantees both cat commands reach the same file.
# Relative: no leading slash, so it is completed from where you stand.
cd /home/goku
cat datasets/iris.csv # reaches /home/goku/datasets/iris.csv
cd /tmp
cat datasets/iris.csv # now means /tmp/datasets/iris.csv, probably an errorThe identical text datasets/iris.csv reached a real file from one directory and a nonexistent one from another. Same string, different result, and that is the trade you accept for the convenience.
# A bare filename is the shortest relative path there is: "right here".
cd /home/goku/datasets
cat iris.csvDON'T:
- DON'T omit the leading
/and expect absolute behavior,home/goku/iris.csvis relative and gets searched from wherever you stand. - DON'T hardcode another user's absolute path such as
/home/vegeta/...into a shared script, it breaks on every machine where that exact path does not exist. - DON'T use a relative path in a scheduled job, a task the system runs automatically from a working directory you did not choose, often your home folder, so the same string can silently target the wrong file.
Path Resolution: The Rule
What. Path resolution is the single rule that turns a path you typed plus the working directory you are in into one real, unambiguous location on disk.
Why. Every command that touches a file has to resolve its path into exactly one place first. If you cannot predict where a path resolves, you cannot predict whether the command will succeed. Once you can perform the resolution by hand, paths stop being guesswork and become arithmetic.
When. Every single time a path appears in a command. There are no exceptions and no special cases.
The rule has exactly two branches, chosen by the first character:
absolute path (starts with "/") -> used exactly as written
relative path (no leading "/") -> working directory + "/" + the pathAn absolute path already describes the full route from root, so the working directory is ignored. A relative path describes only the last part of the route, so the operating system glues it onto the working directory to complete it.
Resolution then reads the completed path one segment at a time, left to right. Two segments are special, and each does exactly one thing:
.keeps resolution where it stands, so./records.csvis a louder way to writerecords.csv...makes resolution climb exactly one level up the tree.
cd /home/goku/project/data
pwd # /home/goku/project/data
# "." stays put
cat ./records.csv # reads /home/goku/project/data/records.csv
# ".." climbs one level
cat ../train.py # reads /home/goku/project/train.py
# segments combine left to right, so ".." twice climbs twice
cat ../../notes.txt # reads /home/goku/notes.txtHere is the same walk written out for ../data/records.csv starting from /home/goku/project/data, so you can watch the cursor move:
start: /home/goku/project/data
read "..": /home/goku/project (climb to parent)
read "data": /home/goku/project/data (descend into data)
read "records.csv": /home/goku/project/data/records.csv (final file)Each line is the location after reading that one segment. The operating system does nothing cleverer than this, it processes a segment, lands somewhere, then processes the next.
The explicit ./ earns its keep in one place, running a program that sits in the current directory. Typing train.sh makes the shell look for a command of that name only in the folders it keeps for programs, while ./train.sh names the file right here.
# the two special segments, listed where you stand
ls -a # . .. records.csvDON'T:
- DON'T read
..as "the root directory", it climbs exactly one level. Two levels needs../... - DON'T apply the trailing part of a path before consuming every
.., segments resolve strictly left to right. - DON'T write
...expecting "up two levels", it is not a thing. - DON'T expect any number of
..to take you above root. From/,cd ..stays at/, because root has no parent.
Working-Directory Sensitivity
What. Working-directory sensitivity is the consequence of the rule: because a relative path is completed using the working directory, the same command can succeed in one directory and fail in another with no change to the command itself.
Why. This is the source of "it worked on my machine", "it worked a minute ago", "it worked in that folder". None of those are mysteries. Each is a relative path resolved against a different working directory, and understanding that turns a baffling failure into a one-line check.
When. Any time you copy a command that worked somewhere else, share a script, or open a terminal in a different folder than usual.
# From inside the project directory, the file is found
cd /home/goku/project
cat data/records.csv # resolves to /home/goku/project/data/records.csv
# Same command, different working directory, now it fails
cd /home/goku
cat data/records.csv # resolves to /home/goku/data/records.csv
# cat: data/records.csv: No such file or directoryThe command never changed. It worked the first time because the working directory completed it into a real file, and failed the second time because a different working directory completed it into a location that does not exist.
There are two everyday cures, and each costs something. Move into the expected directory first with cd, which keeps paths short but relies on you remembering every time. Or use an absolute path, which ignores the working directory entirely but breaks the day a parent folder is moved or renamed.
# Absolute path works from any working directory, because the rule ignores the working dir
cd /home/goku
cat /home/goku/project/data/records.csv # found, no matter where you areThis same rule will later explain a whole family of bugs where a script cannot find the data file sitting right beside it. The script uses a relative path that was correct from the folder it was written in, then it gets launched from a different working directory. Same file, same script, different hidden input, and the same rule you just learned.
DON'T:
- DON'T "fix" a working-directory failure by retyping the path, if the path is relative, retyping it changes nothing.
- DON'T debug a "file not found" by staring at the path alone, check
pwdfirst, the path is only half the story. - DON'T reach for absolute paths everywhere as a reflex, their immunity to the working directory is paid for in fragility when the tree moves.
Lab Exercises
Lab Exercise 1: Resolve by Hand
Do not run anything for this exercise, compute each answer on paper using only the resolution rule.
The working directory is /home/goku/project. Write the single absolute location each path resolves to:
a) data/records.csv
b) /etc/hostname
c) train.pyNow the working directory is /home/goku/project/data. Resolve each of these segment by segment:
d) ./records.csv
e) ../train.py
f) ../../notes.txtLab Exercise 2: Move by Absolute, Then by Relative, Then Confirm
Open a new terminal window, the Ubuntu window on Windows, not VS Code's built-in terminal. Without using cd first, print where you stand and list everything there including hidden entries, then print the OS-stored home path and confirm it matches where you started.
Now use an absolute path to move into /etc and confirm the move. Return home in the fewest keystrokes possible. From home, create a datasets directory if it is not there, move into it with a relative path, and confirm with pwd.
Solution 1: Resolve by Hand
a) data/records.csv -> relative, no leading "/"
/home/goku/project + data/records.csv
= /home/goku/project/data/records.csv
b) /etc/hostname -> absolute, starts with "/"
working directory ignored
= /etc/hostname
c) train.py -> relative
/home/goku/project + train.py
= /home/goku/project/train.py
d) ./records.csv from /home/goku/project/data
"." stays put -> /home/goku/project/data/records.csv
e) ../train.py from /home/goku/project/data
".." climbs once -> /home/goku/project
+ train.py -> /home/goku/project/train.py
f) ../../notes.txt from /home/goku/project/data
".." climbs -> /home/goku/project
".." climbs again -> /home/goku
+ notes.txt -> /home/goku/notes.txt(b) is the one that catches people. The moment a path starts with /, the working directory has zero influence. For the rest, process one segment at a time and write down where the cursor lands after each.
DON'T:
- DON'T forget the
/separator when joining a relative path onto the working directory, the result is.../project/data, not.../projectdata. - DON'T collapse
../..into a single mental "go way up", it is two distinct climbs and resolving them together lands you on the wrong level.
Solution 2: Move by Absolute, Then by Relative, Then Confirm
# Print the absolute path of the current working directory.
pwd
# List ALL entries, including hidden ones and the '.'/'..' pointers.
ls -a
# Print the OS-stored home directory path.
echo $HOME
# Absolute move: leading '/' means start from root, location-independent.
cd /etc
pwd # /etc
cd
# Relative move from home: no leading '/', resolved against the current dir.
mkdir -p datasets # '-p' means no error if it already exists
cd datasets
pwd # /home/goku/datasetsBecause a new terminal window opens in the home directory, pwd and echo $HOME print the identical string at the start. cd /etc works from anywhere because the path is absolute, and the final cd datasets works only because you are standing in home, where datasets exists.
DON'T:
- DON'T use plain
lshere, without-ayou miss the hidden entries the exercise asks for. - DON'T write
cd /datasetsfor the relative step, the leading slash points at root, not at your home folder.
Theory Assessment
Conceptual reinforcement, not a coding section. All four questions with their hints first, then all four answers.
Q1: The character that decides everything, and the input you never typed
State what pwd prints and whether that output is absolute or relative, justifying the claim. Then name the single feature of a path that decides whether the working directory is used or ignored, and explain how the exact text data/records.csv can refer to two completely different files in the same session without one character of the path changing.
Hint: Look at the first character of pwd's output, every time you run it. For the second half, something invisible is being added to the path, so name it and name the command that changes it.
Q2: One step, not a jump
A student claims that .. means "go to the root directory". Correct them precisely, and state what .. actually does in one sentence. Then, starting from the working directory /home/goku/project/data, resolve ../logs/output.txt by hand, showing where you land after each segment.
Hint: Count how many levels one .. moves, and contrast it with ../... For the resolution, process one segment at a time, strictly left to right.
Q3: It broke and nobody touched the file
A command that read a file perfectly an hour ago now reports "No such file or directory", and nobody touched the file. Give the most likely cause and the first command you would run to confirm it. Then describe the two distinct ways to make a fragile relative path reliable, and state one downside of each.
Hint: The path is relative, so ask what hidden input could have changed. For the cures, one moves you and the other removes the dependency on where you are, and each costs something.
Q4: The rule that contradicts itself
A project folder is copied from /home/goku/proj on one machine to /home/vegeta/work/proj on another. Inside it, one file references ../data/raw.csv and another references /home/goku/proj/data/raw.csv. Which reference survives the move, which breaks, and why?
Now hold that against the scheduler case: a script using cat datasets/train.csv works by hand and fails under a scheduler, and the fix there was to make the path absolute. Both cannot be a general rule. Say what actually decides which kind of path is correct.
Separately, the shell keeps the working directory in the variable $PWD, and realpath, which prints the absolute location a path resolves to without opening or reading the file, takes a -m flag on Linux and WSL that resolves a path even when nothing on it exists yet. Write the completed form of a relative path in terms of $PWD, then answer the part that catches people, because plain realpath is not quite as free of the filesystem as it sounds: without -m, what does it require to already exist?
Hint: One reference is anchored to a fixed spot and the other to a relationship between files, so ask which of those two the move preserved. For the last part, "does not read the file" and "does not care whether anything exists" are two different promises, and the tool only makes one of them.
Answer 1:
pwd prints the absolute path of your current working directory, the full route from root down to where you stand.
pwd # always starts with '/'It is absolute because the output always begins with /. A path starting at root is by definition location-independent, which is exactly why pwd is the reliable tool for orientation.
The deciding feature of any path is whether it starts with /. If it does, the working directory is ignored and the path is used as written. If it does not, the operating system completes it as working directory + "/" + path. That one character selects between the two branches of the entire rule.
The same text resolves to two files because the operating system silently adds the working directory to every relative path. data/records.csv really means "the working directory, then data, then records.csv". From /home/goku/project it reaches one file, and after a cd /home/goku the identical text reaches somewhere else. The path never changed, its hidden input did, and cd is what moved it.
DON'T assume pwd could ever return a relative path. DON'T describe this as the path "changing", the path is constant and its resolution moved.
Answer 2:
.. does not mean the root directory. It means the parent of the current directory and climbs exactly one level. Reaching root takes as many .. segments as there are levels between you and it, or simply /. Two levels up is ../...
start: /home/goku/project/data
read "..": /home/goku/project (climb one level)
read "logs": /home/goku/project/logs (descend into a sibling of data)
read "output.txt": /home/goku/project/logs/output.txtDON'T equate one .. with "all the way up". DON'T apply the .. after descending into logs, segments resolve strictly left to right, so the climb happens first.
Answer 3:
The most likely cause is that the working directory changed. The command uses a relative path, the terminal is now open in a different folder than it was an hour ago, and the same text resolves somewhere the file does not exist. The first command to confirm it is pwd. If it shows an unexpected directory, that fully explains the failure.
The two everyday cures:
cdinto the expected directory first, so the relative path resolves correctly. The downside is that you must remember every time, and it is easy to forget.- Use an absolute path, which ignores the working directory entirely. The downside is fragility, because moving or renaming a parent folder breaks every absolute path inside it.
DON'T assume corruption or deletion before checking pwd, the file is almost always intact and the context shifted.
Answer 4:
../data/raw.csv is relative, so it is completed against the working directory, not against the file that holds it. Run from the same place inside the copied project as before, .. still climbs to the project root and the reference resolves. It survives.
/home/goku/proj/data/raw.csv is absolute, hardcoded to a location that does not exist on the second machine. It breaks.
Now the part that matters. The scheduler case and the relocation case point in opposite directions, and neither is a rule about which kind of path is "safer". What decides it is which thing you need to stay true, the location or the relationship. The scheduler script needed a fixed location, because the one thing that varied was the working directory, so anchoring at root fixed it. The moved project needed a preserved relationship between files inside it, because the one thing that varied was the location, so anchoring at root is precisely what broke it. Same two path kinds, opposite correct answers, decided entirely by what is allowed to change.
A relative path is completed into $PWD + "/" + path. $PWD holds the same absolute path that pwd prints, so reading it tells you what every relative path in the current shell is being completed with, and realpath applies that same rule, segment by segment, exactly as you did by hand in Q2.
Here is the part that catches people. "Does not read the file" and "does not care whether anything exists" sound like one promise, and realpath only makes the first. By default the directories along the path must already exist, though the final component may be absent, and if they do not it fails rather than answering. That is the gap -m closes. -m is GNU only, and the realpath macOS ships has no equivalent.
DON'T learn "absolute paths are safer" as a rule, it is true in one of these two cases and false in the other. DON'T assume realpath is existence-blind, it resolves against a real tree unless you ask it not to with -m.
Assignment
Assignment: Reach the File From Three Floors Down
Build this layout under your home directory, then answer every part from inside raw.
/home/goku/
└── project/
├── train.py
└── data/
├── records.csv
└── raw/
└── batch_01.csvStanding in /home/goku/project/data/raw: (a) read records.csv using a relative path with .., (b) read train.py using a relative path, (c) print the absolute location your path in (b) resolves to without reading the file, (d) confirm the working directory through its environment variable rather than the pwd command, and (e) return to the directory you were in before entering raw, using the previous-directory shortcut rather than typing a path.
Hints:
- Count the levels between
rawand each target carefully, one..per level you must climb before descending. - One tool resolves a path and prints it, one variable holds the working directory and is read with a leading
$, and one shortcut remembers exactly one previous directory.
Solution:
# Build the nested layout in one command, then stand in the deepest folder.
mkdir -p ~/project/data/raw
touch ~/project/train.py ~/project/data/records.csv ~/project/data/raw/batch_01.csv
cd ~/project/data
cd raw
# a) Climb one level from raw to data, then read records.csv
cat ../records.csv # reads /home/goku/project/data/records.csv
# b) Climb two levels from raw to project, then read train.py
cat ../../train.py # reads /home/goku/project/train.py
# c) Show where (b)'s relative path resolves, without reading the file
realpath ../../train.py # /home/goku/project/train.py
# d) Read the working directory from its environment variable
echo "$PWD" # /home/goku/project/data/raw
# e) Return to the previous directory, which the shell remembers for you
cd - # /home/goku/project/dataFrom raw, records.csv is one climb up, and train.py is two climbs up. realpath applies the same resolution rule and prints the absolute destination without opening anything, and $PWD exposes the working directory by name, the very value being glued onto every relative path above.
DON'T miscount the climbs, from raw a single .. reaches data, not project. DON'T expect cd - to remember more than one step back, it holds exactly one previous directory.
Additional Resources
Optional, and nothing later depends on either. They go under the rule rather than restating it.
- man7.org -
path_resolution(7)- the authoritative, kernel-level description of how a path becomes a location, edge cases included. - GNU Coreutils Manual -
realpathinvocation - resolving a path to its absolute form, including the-mflag this lesson names.
Summary
A path is an address, a route through the filesystem tree read left to right, slash by slash, from some starting point. Underneath every file command sits one small rule that turns it into a location: a path is either absolute and used as written, or relative and completed against the working directory. It looks almost too simple to be worth a lesson, and yet nearly every confusing moment a beginner has with files traces straight back to it.
The single distinction that matters is where the path starts from. An absolute path starts at root and means the same thing forever, from anywhere. A relative path starts from wherever you are standing, which makes it short and portable but also makes its meaning shift the moment you move. Neither is better, they answer different questions. "Which exact file, no matter where I am?" calls for absolute. "Which file, relative to this project that might live anywhere?" calls for relative.
The working directory is the hinge the whole relative system turns on, and its invisibility is the whole story. People debug paths by staring at the path, because the path is the part they can see. The part that moved is almost always the part they cannot, quietly changed by a cd, a new terminal, or a script launched from somewhere unexpected. Learn to name that hidden input and to ask pwd before you ask anything else, and the mysteries dissolve into arithmetic.
You also have the two ways out and the honest cost of each, and this is not the last you will see of the rule. The same mechanism that decides whether cat data/records.csv finds your file is the one that will later decide whether a saved script can find the data sitting right beside it. When that bug arrives it will not be a new thing to learn, it will be this exact rule wearing a slightly larger coat.
Cheat Sheet
Part A - Reference Table
| Concept | Rule / Syntax | What It Does | When to Use |
|---|---|---|---|
| Print location | pwd |
Shows the absolute path of the working directory | First step in any "not found" bug |
| Change directory | cd <path> |
Moves the working directory | Navigating the tree |
| List contents | ls / ls -a |
Lists entries, -a includes hidden plus . and .. |
Seeing your surroundings |
| Root directory | / |
Top of the filesystem tree | Anchor of every absolute path |
| Absolute path | starts with /, used as-is |
Same target from anywhere | When correctness must not depend on where you stand |
| Relative path | working dir + "/" + path |
Route from where you stand | Everyday work, inside projects |
| Home directory | ~ , $HOME , bare cd |
Your personal base folder | Returning to base |
| This directory | . / ./file |
Stays put | Running a program that sits right here |
| Parent directory | .. / ../ |
Climbs exactly ONE level | Reaching a sibling or an ancestor |
| Read the hidden input | $PWD |
Variable holding the working directory | Reading it by name |
| Resolve without reading | realpath <path> |
Prints a path's absolute form | Confirming where a path lands |
Part B - Compact Code Block
pwd # where am I (the hidden input, always absolute)
ls -a # what's here (+ hidden, . and ..)
echo "$PWD" # read the hidden input by name
echo $HOME # the home path the tilde expands to
cd /etc # absolute move (working dir ignored)
cd datasets # relative move (completed from here)
cd .. # up one level
cd ../models # up, then into a sibling
cd ~ # home (also: bare 'cd')
cd - # back to the previous directory
cat /etc/hostname # absolute: same file from anywhere
cat data/records.csv # relative: PWD + /data/records.csv
cat ./train.py # "." stays put = same as train.py
cat ../../notes.txt # two climbs, then the file
realpath data/records.csv # resolved absolute path, no read