Engineering Toolkit, lesson 1
Files and folders in the shell
Find your way around, look inside files, and move them about safely.
Git, Python projects, databases and containers are all driven from a terminal, and the rest of this module uses one. This lesson gets you around it: where you are, what's inside a file, and how to move files about without losing any. You need a computer and nothing else.
By the end, you can:
Part 1. Where you are, as a path
Read a path, and move between folders with cd.
Open a terminal: Terminal on a Mac, any terminal on Linux, or WSL or Git Bash on Windows. The line ending in $ is the prompt. The shell, the program that reads your commands, always sits in one folder. pwd prints which one, ls lists what's in it, and cd moves you somewhere else.
$ pwd
/home/ana
$ ls
notes projects
$ cd projects/textstats
$ ls
count.py data README.md
$ cd ../../notes
$ pwd
/home/ana/notes
$ cd
$ pwd
/home/anaExample 1.1
Following the session
A new terminal runs the commands in this session. Where is the shell after each cd, and why?
- Start at home
pwd→ /home/anaA new terminal starts in your home folder. On a Mac it would be /Users/ana.
- Go down two folders
cd projects/textstatsA relative path: projects is looked for inside /home/ana, then textstats inside projects.
- Go up two, then down
cd ../../notes→ /home/ana/notesEach
..climbs one level, from textstats to projects to ana. Then notes is looked for there. - Go home
cd→ /home/anacdon its own goes to your home folder, and so doescd ~.
Answer/home/ana/projects/textstats, then /home/ana/notes, then home again.
A path is a route through folders, read one name at a time. If it starts with /, the route starts at the top of the disk, so it means the same thing from anywhere. If it doesn't, it starts where you are. That's why ../../notes works from textstats, but would land somewhere else from any other folder.
Working directory and path
The working directory is the folder the shell is in now, which pwd prints. A path names a file or folder by its route. It's absolute if it starts with /, and relative to the working directory if not. .. means one level up, and ~ your home folder.
../../notes from textstats = /home/ana/notes from anywhere
On a Mac, home is /Users/ana and the shell is zsh, the default since macOS 10.15. Most Linux systems use bash. The two behave alike for everything here, and where their output differs, the lesson says so. To save typing, type the first letters of a name and press Tab: the shell finishes it.
Your turn
You're in /home/ana/projects/textstats/data. You type cd ../../../notes. Where are you now?
.. climb from data to textstats, to projects, to /home/ana. Then notes is looked for there: /home/ana/notes. Counting one level too few gives /home/ana/projects/notes, and one too many gives /home/notes.Part 2. Looking inside a file
Check a file's first lines, last lines and length without opening it.
You rarely need an editor just to see what a data file holds. From inside the textstats folder, three commands answer the first questions: how does it start, how does it end, and how long is it?
$ cd projects/textstats
$ head -n 3 data/reviews.txt
Great kettle, boils fast and looks good.
Stopped working after a week.
Fine for the price.
$ tail -n 2 data/reviews.txt
Returned it, the switch was faulty.
Good value, solid build.
$ wc -l data/reviews.txt
12 data/reviews.txtExample 2.1
A file of reviews
data/reviews.txt holds one product review per line. What are its first three reviews, its last two, and how many are there?
- Read the first lines
head -n 3→ 3 reviewsheadprints the start of a file.-n 3asks for 3 lines; without it you get 10. - Read the last lines
tail -n 2→ 2 reviewstailprints the end of a file, also 10 lines unless you ask for a different number. - Count the lines
wc -l→ 12wccounts lines, words and bytes, and-lkeeps only the lines. On a Mac it pads the number with spaces.
Answer12 reviews, from "Great kettle" to "Good value, solid build."
-n 3 and -l are options. They change what a command does, and usually come before the file it works on. Almost every command takes some, and man head lists all of head's (press q to leave). On Linux, head --help prints a shorter list.
Flag
An option after a command's name that changes what it does, starting with a dash, like -n 3 or -l. Many also have a long form with two dashes, like --lines=3.
head -n 3 data/reviews.txt: a command, a flag, a file
wc -l counts newline characters, so a file whose last line has no newline after it comes out one line short. To read a whole file, less data/reviews.txt shows it a screen at a time: Space for the next page, /kettle to search, q to quit.
For a log that's still being written, tail -f keeps printing new lines as they arrive. It never ends by itself: press Ctrl-C to stop it and get your prompt back.
Your turn
A file has 5,000 lines. Which command prints its last 10, lines 4,991 to 5,000?
tail prints the last 10 lines unless you ask for another number, so tail big.txt and tail -n 10 big.txt do the same. tail -n 4991 prints the last 4,991 lines, head prints the first 10, and wc -l only counts them.Part 3. Copying, moving and deleting
Make, copy, rename and delete files and folders.
Four commands do the housekeeping: mkdir makes a folder, cp copies, mv moves or renames, and rm deletes. Here they back up the script and its data, rename the backup, then throw it away.
$ mkdir -p backup/2026-11
$ cp count.py backup/2026-11/
$ cp -R data backup/2026-11/
$ ls backup/2026-11
count.py data
$ mv backup archive
$ ls
archive count.py data README.md
$ rm -r archive
$ ls
count.py data README.mdExample 3.1
A backup, renamed, then deleted
Copy count.py and the data folder into backup/2026-11, rename backup to archive, then delete it.
- Make the folders
mkdir -p backup/2026-11-pmakes backup first, then 2026-11 inside it, and doesn't complain if they already exist. - Copy a file
cp count.py backup/2026-11/When the last name is a folder, the copy goes inside it with the same name.
- Copy a folder
cp -R data backup/2026-11/-Rcopies the folder and everything in it. Without it,cprefuses. - Rename
mv backup archivemvto a new name in the same place is a rename. Everything inside goes along. - Delete
rm -r archive-rdeletes the folder and everything in it, in one go.
AnswerThe folder is back to count.py, data and README.md.
A folder holds files and other folders, so copying or deleting one means going through everything inside it, at every level. Commands only do that when a flag asks them to. Without one, cp and rm refuse, and say data is a directory, the shell's word for a folder.
Recursive
Done to a folder and everything inside it, at every level. cp -R copies a folder this way and rm -r deletes one. cp -r works too, but the Mac's manual for cp advises -R.
cp -R data backup/ copies a folder, rm -r backup deletes one
rm has no bin: deleted is deleted. cp and mv also replace a file of the same name without asking. Add -i and each of the three asks first, one file at a time. Before any rm -r, run ls on the same path and read what it lists.
Your turn
You're in a folder that holds results, a folder of CSV files. What does cp results results-old do?
-R, cp won't copy a folder. On Linux it says -r not specified; omitting directory 'results'. cp -R results results-old makes the copy. Renaming is mv's job, and it would leave no copy behind.Part 4. Wildcards expand before the command runs
Predict which files a wildcard matches, before you delete anything.
A * in a name matches any run of characters, even none, and ? matches exactly one. Wildcards save typing, and they're also how people delete the wrong files. In this session the data folder holds four files.
$ ls data
access.log reviews.txt scores.csv scores.csv.bak
$ echo data/*.csv
data/scores.csv
$ echo data/scores*
data/scores.csv data/scores.csv.bak
$ rm data/scores*
$ ls data
access.log reviews.txtExample 4.1
What rm data/scores* deletes
Before you run rm data/scores*, find out exactly which files it will delete.
- Print the pattern first
echo data/scores*echoprints whatever it's given, and by then the shell has already swapped the pattern for the names it matches. - Read the matchesdata/scores.csv data/scores.csv.bak
Both names start with scores.
*doesn't care what follows, so the .bak file matches too. - Run the real command
rm data/scores*rmreceives those same two names. It never sees the*, and it deletes both without asking.
AnswerBoth scores files. access.log and reviews.txt stay.
The shell, not the command, works out what a pattern matches. It swaps the pattern for the matching names, in alphabetical order, and only then starts the command. So every command takes wildcards, and echo with the same pattern shows exactly what another command would receive.
rm.Wildcard
A * (any characters, or none) or ? (exactly one character) in a file name. The shell replaces the pattern with every name that matches, in alphabetical order, before the command runs.
echo data/scores* first, then rm data/scores*
Two surprises. * skips names that start with a dot, such as .env, unless the pattern starts with a dot too. And when nothing matches, bash passes the pattern on unchanged, so ls *.json looks for a file called *.json. zsh, the Mac's shell, stops instead: zsh: no matches found: *.json.
Your turn
The folder data has scores.csv, scores.csv.bak and reviews.txt in it. Which files does rm data/*.csv delete?
*.csv matches names that end in .csv. scores.csv.bak ends in .bak, so it survives, and reviews.txt doesn't match at all. -r is only about folders. Wildcards work with any command, because the shell expands them first.Where you'll meet it
When a training run or a service misbehaves on a remote server, often all you have is a shell over SSH. cd to the logs, ls to find them, wc -l to see how big they are, tail -n 50 to read the end and tail -f to watch new lines arrive. Those few commands cover most first looks.
Check yourself
Four questions from across the lesson. Try each one before you look back.
1
You're in /home/ana/projects, and /home/ana has a folder called notes. You type cd ../notes. Where are you now?
.. takes you up to /home/ana first, and then notes is looked up from there. A relative path is read one step at a time from where you stand, so it can go up and then down again.2
A log file has two million lines, and you want to see the latest entries. What do you run first?
tail shows the latest. cat pours all two million lines onto your screen, head shows the oldest entries, and a file that size can be slow to open in an editor. tail -f app.log goes one better: it keeps printing new lines as they're written.3
A folder holds .env, notes.txt and todo.txt. What does echo * print there?
* skips names that start with a dot unless the pattern starts with one too, so .env stays out, just as a plain ls hides it. ls -a shows it.4
A command has been running far longer than it should, and you want your prompt back. What do you press?
fg or end it. Typing exit goes to the running program, not to the shell. Closing the window works, but it also ends everything else that terminal was running.What to remember
1Where you are, as a path
A path that starts with
/is absolute and works from anywhere; any other path starts from the working directory, and each..climbs one level, socd ../../notesfrom textstats reaches /home/ana/notes.2Looking inside a file
head -n 3prints a file's first 3 lines,tail -n 3its last 3, andwc -lcounts its lines; with no-n, head and tail print 10.3Copying, moving and deleting
Folders need a flag to copy or delete,
cp -Randrm -r, andrmhas no bin: deleted is deleted.4Wildcards expand before the command runs
The shell expands a wildcard before the command runs, so
echo data/scores*shows exactly whatrm data/scores*would delete.
Recap and going further
The lesson on one page
pwdprints the working directorylslists it,cdmoves- Tab finishes a name
- Absolute paths start at
/ - Relative paths start where you are
..is up one,~is home
headandtail: 10 lines unless-nwc -lcounts newlinestail -ffollows a log; Ctrl-C stops it
mkdir -p,cp -Randmvrm -rhas no bin and no undo-iasks before replacing or deleting
- The shell expands
*before the command runs *skips names that start with a dotechoa pattern before yourmit
Try this
Find your way around a real project
Open a terminal and go to a project you know, such as a folder of notebooks, using cd and Tab. List it with ls -a. Find its biggest data file, count its lines with wc -l and read its first rows with head. Then make a scratch folder, copy a few files into it with cp, echo a wildcard to see what it matches, and delete the scratch folder with rm -r.
You need: A terminal: Terminal on a Mac, any terminal on Linux, or WSL or Git Bash on Windows.
Look for
- The files
lshides until you add-a, such as.gitor.env. - How
pwdchanges as youcd ..and come back. - What
echo *.csvprints in a folder with no CSV files: bash and zsh answer differently. - Whether
wc -lon a CSV gives one more than the rows your notebook shows, and why: the header line.
The words, in plain language
- Working directory and path
- The working directory is the folder the shell is in now, which
pwdprints. A path names a file or folder by its route. It's absolute if it starts with/, and relative to the working directory if not...means one level up, and~your home folder. - Flag
- An option after a command's name that changes what it does, starting with a dash, like
-n 3or-l. Many also have a long form with two dashes, like--lines=3. - Recursive
- Done to a folder and everything inside it, at every level.
cp -Rcopies a folder this way andrm -rdeletes one.cp -rworks too, but the Mac's manual forcpadvises-R. - Wildcard
- A
*(any characters, or none) or?(exactly one character) in a file name. The shell replaces the pattern with every name that matches, in alphabetical order, before the command runs.
Read next
- Introduction to the Shell, lecture notesThe Missing Semester of Your CS Education (MIT, 2026)The same ground as the video, written out, with exercises at the end.
- The Linux command line for beginnersUbuntu tutorialsA gentle walk through folders, files and moving them about, with screenshots.
- Filename ExpansionBash Reference Manual (GNU)The exact rules for
*and?: sorting, names that start with a dot, and what happens when nothing matches.
Engineering Toolkit overviewSpotted a mistake? Tell us.