MA-CLI1 · Module 1.2
Directories and navigation
Topics: mkdir · cd · ls
Overview
Module 1.2 — Directories and navigation
With paths in hand, Sam builds the tidewatch/ folder tree: create directories, move with cd, and list what is there with ls.
By the end you should be able to: use mkdir / mkdir -p, cd, and ls (-l, -a); sketch a tree before building it; remove empty folders with rmdir.
Scroll Core ideas → worked examples → Quiz. Stay in ~/cli-practice. Plan on roughly 55–60 minutes.
Concepts
Core ideas — building and moving through folders
In the last module you learned how to name a place: absolute paths, relative paths, ., .., ~, and pwd to check where you are. This module teaches you to change the places themselves. You will create folders, walk between them, look inside them, and remove the ones you no longer need. These are the operations behind nearly every piece of command-line work, because before you can copy a note, edit a script, or tidy an archive, you need to be in the right place and have the right shape of folders waiting for the file.
Our running story continues. Sam has been given an empty project called tidewatch, living under the practice sandbox ~/cli-practice. By the end of the module, Sam will have grown it into this shape, and so will you:
tidewatch/
notes/
drafts/
scripts/
archive/
data/
raw/
processed/
Why structure comes first
It is tempting to start by saving files wherever is convenient and tidy up later. In practice, "later" rarely arrives, and files pile up in whichever folder happened to be open. A project with a clear folder shape does something subtle and valuable for you: it answers the question "where does this go?" before you ask it. Raw observations go in one place and cleaned results in another; half-finished writing is separated from finished writing; scripts do not mix with notes.
The command line makes this cheap. A whole tree can be created by typing a single line, and you can look at it again immediately. That speed is why this module comes before anything that touches file contents.
Creating a directory: mkdir
mkdir notes
mkdir (make directory) creates a new, empty folder named notes inside your current directory. Notice that notes is a path argument, and, as you learned in the last module, a relative path begins at wherever you are standing. So the same command typed in two different places creates two different folders. If you run pwd first, you know exactly which one you are about to create.
You can give mkdir several names at once, separated by spaces, and it will create each one:
mkdir notes drafts scripts archive
That single line builds four sibling folders. The names are separate arguments, which is the same "spaces separate words" rule you met earlier.
If the folder already exists, mkdir refuses with a message such as "File exists". That is a polite safety feature: it will not overwrite or merge anything.
Creating nested folders at once: mkdir -p
Suppose you want data/raw, but data does not exist yet. A plain command fails:
mkdir data/raw
The shell reports that there is no such file or directory, because mkdir was asked to place raw inside a folder that is not there. You could first create data, then data/raw, and that works, but the -p option does it in one go:
mkdir -p data/raw
-p stands for parents. It tells mkdir to create any missing parent folders along the route, from the top downward. Here it creates data, then raw inside it. A helpful second property: if some of the folders already exist, -p quietly accepts that and creates only what is missing, with no error. That makes mkdir -p safe to run twice.
Combined with the multiple-argument rule, one line can create a whole branch:
mkdir -p data/raw data/processed
Common confusion:
-pis an option, and options change how the program behaves. It is not a folder name. If you accidentally typemkdir data -p raw, you have given three words and may get unexpected folders. Keep the option before the names, as inmkdir -p data/raw.
Sketch before you build
When a project needs more than two or three folders, resist typing immediately. Take a minute and draw the tree on paper, or in a text file. Write the root name, then indent each folder under its parent, exactly as in the diagram above.
Why is this worth a minute? Because commands are literal. A sketch lets you notice that processed should sit beside raw, not inside it, and that archive belongs at the top level and not under data. Fixing a drawing costs a pencil stroke; fixing a built tree means removing folders and trying again.
Once the sketch looks right, the command nearly writes itself: read the sketch top to bottom and list each leaf folder's full path, because mkdir -p will create all the parents for you. For the tidewatch sketch:
mkdir -p tidewatch/notes tidewatch/drafts tidewatch/scripts tidewatch/archive tidewatch/data/raw tidewatch/data/processed
Six paths, one command, and the parents tidewatch and tidewatch/data come into existence automatically. Compare the typed command with the drawing, and you can check the tree before running it.
Moving around: cd
cd tidewatch
cd notes
cd ..
cd ~
cd
cd (change directory) changes your current working directory. After it succeeds, every relative path is interpreted from the new location. It usually prints nothing when it works, so silence means success, and your only visible clue is a changed prompt or the output of pwd.
Here is how each form behaves. cd tidewatch goes down into tidewatch (a relative path, so you must already be in its parent). cd .. goes up one level. cd ~ goes to your home folder, and cd with no argument does the same. You can also give a long route in a single step, such as cd tidewatch/data/raw, or an absolute one, such as cd ~/cli-practice/tidewatch.
A handy extra is cd -, which jumps back to the folder you were in just before. It is a quick way to toggle between two places.
If cd fails, the message usually reads "No such file or directory". That tells you the path you typed does not exist from here. The cure is nearly always the same two checks: run pwd to see where you are, then run ls to see the real spelling of the folder you want.
Looking inside: ls
ls
ls -l
ls -a
ls tidewatch/data
ls (list) shows what is inside a directory. With no argument it lists the current directory; with a path argument it lists that directory, without you having to move there first.
Plain ls prints names only. It will not show names that begin with a dot, because such hidden entries are normally settings or bookkeeping that you do not need in everyday view.
The -l option gives a long listing, one entry per line, with permissions, owner, size, and modification time before the name. You do not need to decode every column yet; a later module explains permissions. Today, the long listing helps you tell files from folders (a folder's line starts with d) and see sizes and dates.
The -a option shows all entries, including the hidden ones, and includes the two special names . and ... Options can be combined: ls -la means "long listing, including hidden entries".
Common confusion: an empty-looking folder is not always empty. A folder might hold only hidden items.
ls -ais the quick way to be sure.
When an unfamiliar folder is in front of you, ls is the first command to run, and ls -l the second. It is the equivalent of glancing around a room before you move furniture.
Path arguments versus changing directory
There are two ways to act on a folder. You can go there with cd and act on it with short relative names, or you can stay where you are and give the command a longer path:
cd tidewatch/data
ls
ls tidewatch/data
Both produce the same listing. Neither is "more correct"; each has a use.
Going there with cd is comfortable when you plan several steps in one place, because short names are quick to type. Passing the path is better for a single look, or when you want your position to stay put. It also leaves a written record of exactly which folder the command meant, which is valuable when you save commands in notes or share them. A useful rule of thumb: if you will do more than two things in a folder, cd there; if you only need one quick action, pass the path.
Beware of one trap. After cd, your relative paths silently change meaning. If you keep typing commands you wrote while standing somewhere else, they may fail or, worse, act on the wrong folder. When in doubt, pwd.
Removing an empty directory: rmdir
rmdir archive
rmdir (remove directory) deletes a folder only if it is completely empty. If the folder contains anything, even a single file or a hidden item, rmdir refuses and prints a message like "Directory not empty". This is a deliberate safeguard, and a friendly one: it means a typo is unlikely to destroy real work.
There are stronger commands that can delete a folder along with everything inside it. We will meet them in a later module, along with the care they require. For now, treat rmdir as the safe tool for undoing a mistake in your own folder structure, such as a misspelled folder you created a moment ago.
Common mistakes and how to read them
- Wrong place. You built
data/rawinsidenotesbecause you were standing there. Runpwdbeforemkdir, andlsafter it. - Forgetting
-p.mkdir data/rawfails ifdatais missing. Add-p, or create the parent first. - Typing a space inside a name.
mkdir raw datacreates two folders namedrawanddata, not one named "raw data". Useraw_dataorraw-data. - Typos in
cd. The shell cannot guess your intended spelling;cd tidewachsimply fails. Uselsto confirm the name. Many shells also complete names when you press the Tab key, which saves typing and avoids typos. - Going too deep and getting lost.
cd ..steps up one level;cd ~returns home;pwdtells you the truth. - Expecting
rmdirto delete a full folder. It will not, by design. A refusal is information, not a bug. - Assuming silence means failure.
cdandmkdirprint nothing when they succeed. Check withpwdorls.
Self-study checklist
Work through these in your sandbox, with a sheet of paper beside you.
- Draw the tidewatch tree from this lesson, then write one
mkdir -pcommand that builds all six leaf folders. - Explain in your own words what
-padds, and give a case where plainmkdirwould fail butmkdir -psucceeds. - From inside
~/cli-practice/tidewatch/data/raw, write two different ways to move to~/cli-practice/tidewatch/scripts. - After
cd ~/cli-practice/tidewatch/notes, say which folderls ..lists, and which folderls ../datalists. - Say when you would choose
ls -loverls, and when you would add-a. - Explain why
rmdirrefuses a folder that contains one empty-looking hidden file. - Choose, for each of these tasks, whether to
cdfirst or pass a path: (a) one quick look insidedata/raw; (b) five edits inscripts.
If a bullet feels uncertain, reread its section once, then answer again without looking.
Examples
Worked examples — growing the tidewatch tree
In these five stories Sam turns an empty practice sandbox into the folder shape of the tidewatch project. Type every command in your own terminal inside ~/cli-practice. Silence after mkdir or cd means the command worked, so rely on pwd and ls to confirm. Paths below assume a home folder of /Users/sam; yours will differ.
Example A — Sketch first, then one command
Scene. The project lead lists what the team needs: a place for notes, drafts, scripts, finished material, and raw and cleaned data. Sam resists the urge to start typing and draws the tree first.
tidewatch/
notes/
drafts/
scripts/
archive/
data/
raw/
processed/
Reading the sketch, Sam notices that raw and processed are siblings under data, and that archive sits at the top level. Then Sam builds it.
cd ~/cli-practice
mkdir -p tidewatch/notes tidewatch/drafts tidewatch/scripts tidewatch/archive tidewatch/data/raw tidewatch/data/processed
ls -R tidewatch
Expected outcome. The first two commands print nothing. ls -R lists tidewatch and then each subfolder in turn: the top level shows archive data drafts notes scripts, and tidewatch/data shows processed raw. The leaf folders are empty.
Interpretation. Each argument is the full route to a leaf, and -p created tidewatch and tidewatch/data along the way. Comparing the command with the sketch, line by line, is how Sam knew it was right before pressing Enter. The -R option on ls means "also list inside subfolders", a quick way to see a whole branch at once.
Takeaway. Draw the tree, read off each leaf path, and let mkdir -p build the parents.
Example B — A missing parent, and a safe repeat
Scene. Sam wants a place for weekly reports and, without thinking, asks for a nested folder whose parent does not exist.
cd ~/cli-practice
mkdir tidewatch/reports/spring
mkdir -p tidewatch/reports/spring
mkdir -p tidewatch/reports/spring
ls tidewatch/reports
Expected outcome. The first command fails with a message saying it cannot create tidewatch/reports/spring because there is no such file or directory (the exact wording depends on your system). The second command prints nothing and succeeds. The third also prints nothing, with no complaint that the folder exists. The ls shows spring.
Interpretation. Plain mkdir will not invent missing parents, so it stopped at reports. Adding -p told it to create whatever was missing. Repeating the command did no harm, because -p creates only what is absent and does not treat an existing folder as an error. That makes it a comfortable choice for setup steps you may run more than once.
Now Sam decides reports belong elsewhere and removes the experiment, deepest folder first:
rmdir tidewatch/reports/spring tidewatch/reports
ls tidewatch
Both folders were empty, so both vanish, and the listing shows the original five folders.
Takeaway. Use -p when a parent might not exist; read the error as a clue that a link in the chain is missing.
Example C — Going there versus passing the path
Scene. Sam wants to peek inside data to check its two subfolders, and then do several things in scripts. Sam decides to use a different approach for each job.
cd ~/cli-practice
ls tidewatch/data
pwd
cd tidewatch/scripts
pwd
ls ..
cd ../data/raw
pwd
cd ~
cd -
pwd
Expected outcome. The first ls prints processed raw. The first pwd still shows /Users/sam/cli-practice, because ls with a path argument does not move you. After cd tidewatch/scripts, pwd shows .../tidewatch/scripts, and ls .. lists the parent, tidewatch: archive data drafts notes scripts. The next pwd shows .../tidewatch/data/raw. Finally cd ~ goes home, cd - returns to the previous folder (.../tidewatch/data/raw, which the shell usually announces), and the last pwd confirms it.
Interpretation. For a single quick look, passing the path kept Sam's position unchanged, which is exactly what a quick look needs. For work in scripts, moving there with cd meant later commands could use short names. Notice cd ../data/raw from scripts: it climbed one level to tidewatch, then walked down two. The cd - trick toggles between two spots.
Takeaway. Pass a path for a one-off action; cd when you will stay a while; and check with pwd after moving.
Example D — The folder that looks empty
Scene. Sam wants to keep drafts under version-friendly bookkeeping and adds a small hidden marker file there. Later, a teammate asks whether drafts is empty, and plain ls prints nothing.
cd ~/cli-practice/tidewatch/drafts
touch .keep
ls
ls -a
ls -l
ls -la
Expected outcome. Plain ls prints nothing. ls -a prints ., .., and .keep. ls -l also shows no entries, because -l alone still hides dot-names (some systems print only a total 0 line). ls -la shows the same three entries as ls -a, each on its own line with permissions, owner, size, and date columns first. The line for . and .. begins with d, marking folders, while .keep begins with -, marking an ordinary file.
Interpretation. Names beginning with a dot are hidden from ordinary listings, so the folder looks empty even though it holds one file. -a reveals everything, including the two special entries . (this folder) and .. (its parent) that exist in every directory. -l adds the detail columns, and combining them as -la gives both. Sam tells the teammate, correctly, that drafts is not empty. This is also exactly why rmdir drafts would now refuse.
Takeaway. An empty-looking folder may hold hidden entries. Use ls -a before concluding that nothing is there, and ls -l when you want details.
Example E — Wrong place, and the refusal of rmdir
Scene. Sam is in notes and, thinking of the data folder, types a build command out of habit. A moment later, a listing shows something unexpected.
cd ~/cli-practice/tidewatch/notes
mkdir -p data/raw
ls
pwd
rmdir data
rmdir data/raw data
ls
Expected outcome. ls shows a new data folder inside notes, and pwd confirms Sam was in .../tidewatch/notes. rmdir data fails with a message such as "Directory not empty", because data still holds raw. The next command succeeds silently, and the final ls no longer shows a data folder inside notes (it may still show any note files you made in the previous module).
Interpretation. The command itself was correct; the location was wrong, so a duplicate branch grew inside notes. Sam's repair was careful: rmdir refused to remove data while raw was inside it, and it only succeeded once data/raw was removed first. Order matters: deepest folder first, then its parent. Because rmdir only deletes empty folders, a slip here cannot destroy any real work.
Sam finishes by confirming that the real data folder is untouched:
ls ~/cli-practice/tidewatch/data
The listing shows processed raw, as designed.
Takeaway. When a command goes to the wrong place, run pwd and ls, then undo it with rmdir, deepest first. A refusal from rmdir is protection.
What the day produced
At the end, Sam's tree matches the sketch from Example A, with one small addition, the hidden .keep file in drafts. If you can retell each story from memory and predict each outcome, you have the module.
Practice check — directories
Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.
1.Sam runs `mkdir -p tidewatch/data/raw` and none of the folders exist yet. What happens?
2.Sam types `mkdir data/raw` where `data` does not exist, and sees 'No such file or directory'. What is the smallest fix?
3.Sam is in `~/cli-practice/tidewatch/notes`. Which command lists the contents of `~/cli-practice/tidewatch` without moving?
4.Plain `ls` in `drafts` prints nothing, but the folder may still contain something. Which command reveals hidden entries?
5.Sam stands in `~/cli-practice/tidewatch/data/raw`. Which command reaches `~/cli-practice/tidewatch/scripts`?
6.Sam needs one quick look inside `data/raw` and then wants to stay in the current folder. What is the best approach?
7.Sam runs `rmdir data` on a folder that contains an empty folder named `raw`. What happens, and why?