Skip to content

Metadata Card

  • Prerequisites: Ch1 (What Is a Computer)
  • Estimated time: 40 min
  • Core difficulty:
  • Reading mode: Easy stroll
  • Completion marker: Can create, move, and delete files in the terminal; understands PATH and environment variables; can use wildcards and pipes to combine commands

Your Progress

You're still in the workshop before setting out. The previous chapter's desk is covered with an exploded view of the computer — you've figured out what's inside, but now you need to learn how to talk to it.

When you finish looking over everything, you find the workshop master is gone.

On the table is a map — a yellowed parchment with a strange symbol drawn on it: $.

Underneath the map is a note:

"I'm in the basement machine room. Come find me. But first you need to learn how to talk to the computer — I don't think you want to click a mouse every single time. Take the left door and open the terminal. We'll meet downstairs."

You look to the left. There's a door. On it is written: TERMINAL.

Your Task

After this chapter, you will no longer fear that black-and-white window. You'll know how to use it — how to browse files, create project directories, kill broken programs, and run your first line of code.

The terminal is not a "relic from old times" — it's the developer's most used tool. Someone fluent in the terminal works three times faster than someone using only a mouse. Not because you type faster, but because you can string operations into a single command, combine them, and even write scripts that run all night.

Today's goal: Learn to talk to your computer with the keyboard.

Chapter Layers

  • Required reading: pwd, cd, ls, mkdir, touch, cat, rm, and basic output redirection (> and >>)
  • Optional reading: PATH environment variable, wildcards (*, ?), pipes (|) to combine commands
  • Advanced: Regular expressions, Shell config files (.bashrc/.zshrc), custom environment variables

This chapter will NOT require you to understand

  • Full regex syntax — just know that grep can search by pattern
  • Shell scripting (for loops, if conditions, functions)
  • System config file recovery techniques

The Breakthrough · Tracing the Origins

Round 1: First Conversation

"Can you talk to your computer?"

The workshop master stands before the left door marked "TERMINAL," arms crossed. "Not with a mouse — like greeting an old craftsman — speak its language."

He knocks on the door. A low voice from inside asks: "Who?"

"Your turn." He nods toward the handle. "Push it open. Say something."

You push open the Terminal door. Inside is pitch black. Only a small blinking cursor — a vertical line, flickering at the end of a line of text.

On the screen, just one line:

steven@workshop:~$

This $ is your prompt. It's talking to you:

"I'm ready. Tell me what to do next."

You can see several parts of the prompt:

  • steven — who you are (currently logged-in username)
  • workshop — the machine (hostname)
  • ~ — your current directory (~ is shorthand for home directory)
  • $ — this is a regular user shell

Try typing a few letters. First enter whoami, then press Enter.

bash
# Tell me who you are
whoami

# Expected output:
# steven

Language: Shell (Bash/Zsh) How to run: Open terminal, type the command, press Enter Expected output: Your username Try it: hostname to see the machine name, date to see the date and time, uptime to see how long the computer has been running

The whoami you typed is a command; the Enter you pressed is execute. The terminal passes your command to the Shell — the Shell is a program that parses your input, finds the corresponding executable file (remember programs from Ch1?), executes it, and displays the output on screen.

You may not realize it yet, but you're already talking to your computer.

Round 2: Finding Your Way — Directories and Paths

You've successfully said one word to the terminal — whoami — and it replied with your name. But then you realize something: in this darkness, you don't even know where you're standing.

It's like entering a massive underground workshop. You hear echoes but can't see the floor beneath your feet. You feel along the wall and take two steps — "Which corner of the workshop am I in?"

"Where are you?" — this is always the first question to ask in the terminal.

In the file system, you always have a "current directory." The ~ in your prompt tells you you're in your home directory.

bash
# Print current working directory
pwd

# Expected output:
# /home/steven

Language: Shell (Bash/Zsh) How to run: Type pwd, Enter Expected output: Full path of current directory Try it: First cd /tmp, then pwd, and see how the path changes

pwd = Print Working Directory

The file system is a tree — root is /, then it branches into home, usr, etc, var... Each branch can branch further. /home/steven is your position in the tree.

You can move through this tree:

bash
# Switch to /tmp directory
cd /tmp

# See what's in /tmp
ls

# Go up one directory level
cd ..

# Go back to the previous directory (remember /tmp?)
cd -

Language: Shell (Bash/Zsh) How to run: cd <path>, ls without arguments Expected output: cd has no output, ls shows files and subdirectories in the current directory Try it: Jump between directories with cd, check your position with pwd each time

Paths come in two forms:

  • Absolute path: Starts from root /, e.g., /home/steven/projects
  • Relative path: Starts from the current directory, e.g., ../steven/projects (.. means parent directory, . means current directory)

Press the Tab key for auto-completion — type a few characters and press Tab; the Shell will complete the rest. If there are multiple possibilities, press Tab again to list all options. Make this a habit — it saves more time than you can imagine.

Round 3: Touch This World — File Operations

"Good, you know where you are." The workshop master's voice comes from somewhere. "But standing still isn't useful. You need to do something."

You look around — an empty black-and-white world, nothing here. "But there's nothing here..."

"Then create something." His voice carries a smile. "Isn't there material on the workshop floor? Pick up a rune stone and carve your name on it."

Now you know where you are. Time to get to work.

You find a blank rune stone in a corner of the workshop — its name is first-try.txt.

bash
# Create an empty file
touch first-try.txt

# Confirm it exists
ls -l first-try.txt

Language: Shell (Bash/Zsh) How to run: First cd ~ to your home directory, then enter commands one by one Expected output: ls -l shows file size, permissions, modification time What happened: A new file first-try.txt appears in the current directory, size 0 bytes

touch literally means "to touch." If the file doesn't exist — create it. If it already exists — update its modification time.

Now write something inside it:

bash
# Use echo to write text into a file
echo "Hello Workshop!" > first-try.txt

# View file contents
cat first-try.txt

# Expected output:
# Hello Workshop!

Language: Shell (Bash/Zsh) How to run: Make sure first-try.txt exists first, then run these two commands Expected output: Terminal prints "Hello Workshop!" Try it: Use echo "Another line" >> first-try.txt (two >) to append instead of overwrite

There's a subtle symbol here — >.

> is called redirection. You're not "telling the Shell to write output to a file" — you're saying: "Take the output of the echo command, and instead of displaying it on screen, redirect it into the file."

bash
# Write the date to a file
date > timestamp.txt

# Write the process list to a file
ps aux > processes.txt

# See what was written
cat processes.txt | head -5

If the file already exists, > will overwrite it. >> appends to the end of the file without overwriting.

Round 4: Directory Operations — Setting Up Camp

You've poked a few files into existence in the terminal, like placing a few stone slabs on an empty lot. But you quickly realize a problem — the slabs are scattered on the ground. You won't be able to find anything in no time.

"Look around you." The workshop master's voice comes from above. "My workshop has sections: forging area on the left, materials on the right, blueprints hanging on the wall. What about your terminal?"

You look down at the pile of files — they're all mixed together, like throwing screwdrivers and kitchen spatulas into the same drawer.

"You need to build some shelves."

You decide to create a dedicated directory for this adventure — "my project."

bash
# Create a directory
mkdir my-project

# Enter the directory
cd my-project

# Create subdirectories inside
mkdir src docs

# See the structure
ls -l

# Expected output:
# drwxr-xr-x 2 steven steven 4096 Jun 23 16:00 docs
# drwxr-xr-x 2 steven steven 4096 Jun 23 16:00 src

Language: Shell (Bash/Zsh) How to run: Enter commands one by one Expected output: ls -l shows two subdirectories Try it: mkdir -p project/{src,test,docs} to create a nested directory structure in one shot

Deleting is simple, but be careful — deletion doesn't go through the trash.

bash
# Delete a file
rm first-try.txt

# Delete an empty directory
rmdir docs

# Delete a directory and all its contents (use with caution!)
rm -rf src

Language: Shell (Bash/Zsh) How to run: Confirm the file/directory exists before running Note: rm -rf is dangerous — it recursively deletes everything without confirmation. Always check the path you're about to delete before running.

bash
# Safe practice: first ls the path you want to delete
ls src/
# After confirming:
rm -rf src/

# Or use -i for interactive mode, confirming each one
rm -ri src/

Advanced: The following three rounds (PATH, wildcards, pipes) are not essential terminal survival skills. You can read through the main story first and come back to explore them later.

Round 5: Environment Variables and PATH — The System's Search Path

"You typed whoami and it found it. You typed ls and it found it too." The workshop master has appeared beside you. "But have you considered — how does the computer know where ls is? There's no program called ls lying around in your terminal."

You pause. "That's right... I never thought about that."

"You have a map on you." He points at your chest. "You carry it everywhere, but you can't see it yourself."

You're carrying some "invisible things" — environment variables.

Environment variables are key-value pairs maintained by the Shell, telling programs important info: where your home directory is, which editor to use, where to find executable files.

bash
# View all environment variables
env | head -10

# View a single variable
echo $HOME
echo $USER
echo $SHELL
echo $PATH

Language: Shell (Bash/Zsh) How to run: Just type them in Expected output: Your home directory path, username, shell path, command search path Try it: echo $LANG to see system language, echo $PWD to see current directory

Notice the $ symbol — in the Shell, $variable_name means referencing this variable. Earlier the prompt showed ~ instead of $HOME, and they're mostly equivalent.

The important one is PATH.

bash
# See what's in PATH
echo $PATH

# Example output:
# /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/home/steven/.local/bin

Language: Shell (Bash/Zsh) How to run: Just type it in Expected output: A string of colon-separated directory paths Try it: which ls to see which directory the ls command is in, which python3 to see where Python is

PATH is the "map" the Shell uses to find executable programs. When you type ls, the Shell traverses each directory in PATH in order:

  1. First check /usr/local/bin — is there an ls?
  2. Not there? Check /usr/bin → Found it! Execute.

If two directories have a file with the same name, only the first one found is executed. This is why after installing a new program, you sometimes need to add its directory to the front of your PATH to override the system default version.

Setting your own environment variable:

bash
# Set a variable (only effective in the current terminal session)
export MY_VAR="Hello from my shell"

echo $MY_VAR
# Hello from my shell

To make it permanent, write it into the Shell's config file — for Bash it's ~/.bashrc, for Zsh it's ~/.zshrc:

bash
# Use echo to add a line to the config file
echo 'export MY_VAR="Hello from my shell"' >> ~/.bashrc

# Reload the config file
source ~/.bashrc

Language: Shell (Bash/Zsh) How to run: First manually run export to test, then write that line into the config file Try it: Add ~/my-bin to PATH: export PATH="$HOME/my-bin:$PATH" (test first, then write into config)

Advanced continues: Wildcards let you operate on files in bulk — practical, but not essential on day one.

Round 6: Wildcards — Batch Spellcasting

You've created directories and placed files. Then you run into a problem: you have twenty log files to rename, or thirty test files to move into a subdirectory.

You start typing filenames one by one — by the fifth one, your hand is cramping.

"Have you heard of those spellcasting tools in the workshop?" The workshop master takes an iron rod off the wall. "It can affect a whole row of weapons, not just one at a time."

You have a bunch of files to process. Doing them one by one is too slow. The Shell's wildcards are made for this.

bash
# First create some test files
touch report-2024-01.txt report-2024-02.txt report-2024-03.txt
touch photo-vacation.jpg photo-party.jpg note.txt

# View all report files
ls report-*

# Expected output:
# report-2024-01.txt report-2024-02.txt report-2024-03.txt

# View all .txt files
ls *.txt

# View all files starting with photo-
ls photo-*.jpg

# View files with numbers in their name
ls *[0-9]*

Language: Shell (Bash/Zsh) How to run: First create the files, then try various wildcards Expected output: File list matching the wildcard pattern Try it: ls report-2024-0[13].txt to only match 1 and 3, skipping 2

Wildcard matching rules:

PatternMatchesExampleMatch
*Any characters (0 or more)*.txtAll txt files
?Any single characterreport-?.txtreport-1.txt, report-a.txt
[abc]One from a setreport-[13].txtreport-1.txt, report-3.txt
[a-z]Range[a-z]*.txttxt files starting with lowercase letter
bash
# Batch operation example: rename all .png files to .jpg

# First simulate — just rename
for file in *.png; do
 mv "$file" "${file%.png}.jpg"
done

# Safe approach: first print, don't modify
for file in *.png; do
 echo "mv -- '$file' '${file%.png}.jpg'"
done
# Remove echo to actually execute

Language: Shell (Bash/Zsh) How to run: Execute in a directory containing .png files Note: Test with echo first, then remove echo to actually rename

Advanced continues: Pipes are the essence of Unix philosophy. Read the concept now; look up specific commands when you need them.

Round 7: Pipes — Chaining Commands

"You have directories, files, wildcards — but there's one thing you haven't tried: linking two commands together."

The workshop master takes two iron pipes and connects them end to end. "If the forging fire could flow directly to the quenching pool — you wouldn't have to carry the red-hot iron block across the room."

He taps the connected pipe. "Same with commands. The output of one command can be the input of the next. No need to stop and look in between."

This is one of the most powerful tools you'll learn.

The pipe symbol | does one thing: takes the output of the command on the left and uses it as input for the command on the right.

Imagine a conveyor belt — water flows from upstream through different filters, eventually becoming pure water.

bash
# Count files in the current directory
ls | wc -l

# Find a process
ps aux | grep chrome

# Check the last 5 lines of system log containing "error"
tail -100 /var/log/syslog | grep -i error

Language: Shell (Bash/Zsh) How to run: Enter commands one by one Expected output: First command outputs file count, second lists processes containing "chrome" Try it: ls -la | sort -k5 -n | tail -3 to find the three largest files in the current directory

Pipes let you combine an infinite number of commands, each doing one thing and doing it well — this is the core of Unix philosophy.

Example — you want to know: "Which is the largest .log file in the current directory?"

bash
# Step by step:
# 1. All .log files
ls *.log

# 2. With sizes shown
ls -lh *.log

# 3. Sorted by size (human-readable sort needs -h)
ls -lh *.log | sort -k5 -h

# 4. Just the largest one
ls -lh *.log | sort -k5 -h | tail -1

# 5. Only the filename (no size info)
ls -lh *.log | sort -k5 -h | tail -1 | awk '{print $NF}'

Language: Shell (Bash/Zsh) How to run: Execute in a directory containing .log files Try it: Start with ls -lh *.log, add pipes step by step to understand what happens at each stage

You don't need to memorize all the commands and options — awk, sort, grep — you'll get familiar with them over time. The key is understanding the pipe mindset: break the problem into small steps, each step outputs a result that feeds the next.

Common Pitfalls

Trap 1: rm -rf / — Irreversible Deletion

You've definitely heard this joke. rm -rf / recursively deletes everything under the root directory — meaning the entire system gets wiped.

But modern systems have protection — you can't actually run this:

bash
# Safe! Won't execute
rm -rf /

# rm: it is dangerous to operate recursively on '/'

Even if you try to force it, you need --no-preserve-root. And even then, since many directories are locked by the system, you'd mostly just destroy your own user data.

What's truly dangerous is your own mistake: rm -rf ./build when you're in the root directory ~ instead of your project directory. Get in the habit of pwd and ls before rm.

Trap 2: Filenames with Spaces

bash
# Problem: this file has a first and last name
touch My Important File.txt

# Trying to delete
rm My Important File.txt
# rm: cannot remove 'My': No such file or directory
# rm: cannot remove 'Important': No such file or directory
# rm: cannot remove 'File.txt': No such file or directory

The Shell treats spaces as argument separators. The above command tries to delete three files: My, Important, and File.txt.

Solution: Always quote filenames.

bash
rm "My Important File.txt"

# Or escape spaces with backslash
rm My\ Important\ File.txt

Trap 3: ~ Is Not the Current Directory

In the terminal, ~ always refers to your home directory, NOT the current directory. If you cd /tmp and then rm -rf ~/build, you're not deleting /tmp/build — you're deleting /home/steven/build.

If you need to operate on the current directory, use . explicitly:

bash
rm -rf ./build # 'build' in the current directory
rm -rf build   # also 'build' in the current directory (no /)
rm -rf ~/build # 'build' in your home directory — completely different place!

Trap 4: Confusion mixing pipes and redirection

bash
# This also redirects error output to the file
command > output.txt 2>&1

# This only redirects standard output
command > output.txt

2>&1 means: file descriptor 2 (stderr, standard error) redirects to file descriptor 1 (stdout, standard output)'s current location.

You don't need to remember this right now. But when you see > and | used together, just know there's a concept of "output streams."

Final Challenge

  • Warm-up (5 min, required)
  1. Open terminal, use pwd to confirm your location, ls to see what's there.
  2. Create a directory called practice under your home directory, go into it, create a file called hello.txt, write a line of text, view it.
  3. Run echo $PATH, find at least one directory you recognize among the :-separated paths (like /bin or /usr/bin).
  4. Use ls / | sort to view files in the root directory, pipe to | head -10 to only see the first 10.
  • Challenge (30 min, optional)
  1. Pipe chain practice: Find the 3 newest log files in /var/log:
bash
ls -lt /var/log | head -4 | tail -3

Understand what happens at each step.

  1. Batch rename: In the practice directory, create 10 test files test-{1..10}.txt, then use wildcards to rename .txt to .bak. First test with echo, then execute when confirmed.
bash
# Create files
touch test-{1..10}.txt

# Test rename
for f in test-*.txt; do echo mv "$f" "${f%.txt}.bak"; done

# Actually execute
for f in test-*.txt; do mv "$f" "${f%.txt}.bak"; done
  1. Explore PATH: Use which to find where python3, grep, and ls are located. Use file command to view their file types.
  • Troubleshooting: Each command below has a problem — can you spot it?
bash
# Problem 1:
rm -rf ~/build
# (You meant to delete 'build' in the current directory)

# Problem 2:
cd ~
rm -r practice
# (Everything is gone — wait, what?)

# Problem 3:
ls -l | grep .txt
# (All files appear, not just .txt)
# Hint: grep's argument is a regex — '.' matches any character
# Correct approach:
ls -l * .txt # wrong, space issue
ls -l *.txt # correct, wildcard

Checklist

  • [ ] You can navigate the file system freely with cd, ls, pwd.
  • [ ] You can create and manage files and directories with touch, mkdir, cp, mv, rm.
  • [ ] You understand what PATH is and know that $ references a variable.
  • [ ] You can use *, ? wildcards for batch operations.
  • [ ] You can chain commands with |.
  • [ ] You know filenames with spaces need quotes.
  • [ ] You know the danger of rm -rf and have developed the habit of ls before delete.
  • [ ] You know the difference between > and >> (overwrite vs append).

Common Sticking Points

"Pressing up/down arrows does nothing?" Up/down arrows recall command history. Try a few times. If it still doesn't work, make sure you're using Bash or Zsh.

"cd .. does nothing?" cd .. doesn't produce any output — it just changes the current directory. Use pwd to confirm where you are.

"How do I find where a command is?" Use which <command_name>. If it returns /usr/bin/ls, that's where it is. If it returns "not found," it's either not in your PATH or not installed.

"I broke my config file. What now?" Most systems have backups. If ~/.bashrc is corrupted, you can copy /etc/skel/.bashrc back, or open a new terminal session to check for a default config. If completely broken, create a clean one:

bash
echo "# Default bashrc" > ~/.bashrc
source ~/.bashrc

"Why doesn't my ~/.bashrc change take effect?" You need to reload it after modification. Run source ~/.bashrc or open a subshell in the current terminal. You can also close and reopen the terminal.

No Need to Understand Now

  • Shell scripting (for loops, if conditions, functions) — this chapter only uses the simplest for loop as a batch operation example
  • Complex text processing commands like awk, sed, xargs — you'll learn them naturally
  • What /dev/null really is — just know it's a "black hole" for now
  • Process management kill signal types (SIGTERM vs SIGKILL) — Ch1 mentioned it, but you don't need all the signals
  • Regular expressions — grep supports regex, but this chapter only uses plain text search
  • How to customize the PS1 prompt — cool but not needed yet

Traveler's Notes

The terminal is your conversation window. The Shell parses your commands, $ awaits your next instruction.
cd moves you around the map, ls looks around, pwd confirms your position.
File operations carved into memory: touch to create, mkdir to set up camp, rm to destroy but handle with care.
PATH is the Shell's directory list for finding programs, $ retrieves a variable's value.
Wildcards are batch spellcasting, pipes are conveyor belts.
Spaces are argument separators — wrap filenames in quotes.
Never forget: ls first, confirm the path, then execute destructive operations.

Preview of Next Stop

You can now navigate the terminal fluently — create, delete, move, find, no problem.

But soon you'll encounter a headache all developers face: you changed some code, changed it wrong, want to go back to an hour ago — but you already saved.

Next chapter, you'll get a time machine: Git. You'll be able to rewind to any moment, starting over as if you never made a mistake. Remember what the workshop master said — "Don't worry if you break it, we have backups."

Built with VitePress | Software Systems Atlas