The Command Line
The shell is the cockpit of data engineering — every database, container, server, and pipeline tool is ultimately driven from a text prompt. This lab gets you comfortable moving around, manipulating files, and chaining small commands into something powerful. Type every command; the fluency comes from your fingers.
Open your terminal (on Windows, your WSL2 Ubuntu terminal from Chapter 00). That's all you need — the shell is already installed. Keep this page beside the terminal and run each command as you read. If a command isn't found on macOS, install Homebrew (brew.sh) and re-try; most tools here are built in.
What "the command line" actually is
When you open a terminal, a program called a shell is waiting to read what you type. The most common shell is bash (or its cousin zsh, the macOS default — they behave almost identically for our purposes). You type a command, press Enter, the shell runs it, prints output, and waits for the next one. That's the entire loop.
A command has three parts:
Why the command line (when GUIs exist)
| The shell gives you… | Why it matters for data work |
|---|---|
| Reach | Remote servers and containers have no GUI — only a shell. This is how you operate them. |
| Repeatability | A command is text you can save, version, and re-run. Clicking is not reproducible. |
| Composability | Small tools snap together with pipes to do things no single app does. |
| Speed at scale | Rename 10,000 files or scan a million-line log in one line — no scrolling. |
Making & moving files
Let's create a small workspace and practice. Type these in order:
cd ~ # start at home
mkdir -p cli-practice/data # make nested folders (-p makes parents as needed)
cd cli-practice
touch notes.txt # create an empty file
echo "hello data" > data/greeting.txt # write text into a new file
cp data/greeting.txt data/greeting-backup.txt # copy
mv notes.txt README.txt # move/rename
ls -R # list recursively to see the whole treels -R shows README.txt and a data/ folder containing greeting.txt and greeting-backup.txt. If mkdir complained, you may have skipped -p — it creates intermediate folders for you.
rm file deletes a file; rm -r folder deletes a folder and everything in it — permanently, with no recycle bin. Never run rm -rf on a path you haven't double-checked, and never on / or ~. Pause and read the path before pressing Enter. This habit will save you one day.
Looking inside files
Data engineers stare at files constantly — peeking at a CSV, tailing a log. The toolkit:
cat data/greeting.txt # dump the whole file to the screen
head -n 5 bigfile.csv # first 5 lines (great for peeking at headers)
tail -n 5 bigfile.csv # last 5 lines
tail -f app.log # FOLLOW a log live as it grows (Ctrl-C to stop)
wc -l bigfile.csv # count lines (rows) — your quick "how big is this?"
less bigfile.csv # scrollable viewer; press q to quit, / to searchYou'll often get a multi-gigabyte file you can't open in a spreadsheet. head shows you the columns and a few rows instantly without loading the whole thing — the first move when meeting any new dataset.
Pipes & redirection — where the shell gets powerful
This is the big idea. Two operators let small tools combine:
|(pipe) — sends the output of one command as the input of the next.>and>>(redirect) — send output to a file (>overwrites,>>appends).
# How many lines mention "error" in a log?
cat app.log | grep "error" | wc -l
# Save the first 100 rows of a big CSV to a sample file
head -n 100 big.csv > sample.csv
# Append a line to a file without erasing it
echo "2026-06-21 run ok" >> run.logEach tool does one thing well; pipes compose them into pipelines. This is the same idea — small stages, data flowing through them — that underlies every data pipeline you'll build later. You're already thinking like a data engineer.
A taste of data wrangling
Let's make a tiny CSV and answer questions about it with only the shell — no spreadsheet, no Python yet.
# create a small CSV
cat > data/sales.csv <<'EOF'
date,region,amount
2026-06-01,us,120
2026-06-01,eu,80
2026-06-02,us,200
2026-06-02,eu,95
EOF
wc -l data/sales.csv # how many lines (incl. header)?
head -n 1 data/sales.csv # the header row
grep ",us," data/sales.csv # only US rows
grep ",us," data/sales.csv | wc -l # how many US rows?
cut -d, -f3 data/sales.csv | tail -n +2 # just the amount column, skip headerwc -l → 5 (4 data rows + 1 header). The grep ",us," lines show the two US rows; piping to wc -l → 2. cut prints the four amounts in file order: 120 / 80 / 200 / 95. You just filtered and projected columns — the shell equivalent of a SQL WHERE and SELECT.
Survival kit
The handful of extras that make daily life smooth:
| Command / key | Does |
|---|---|
| Tab | Auto-complete file/command names — use it constantly |
| ↑ / Ctrl-R | Previous command / search command history |
| Ctrl-C | Stop the running command |
Ctrl-L / clear | Clear the screen |
man ls / ls --help | Read a command's manual / quick help |
which python | Show which program runs for a name |
grep -r "TODO" . | Recursively search text in files under . |
find . -name "*.csv" | Find files by name pattern |
✓ Check yourself
Answer from memory before opening each one.
-
A script that reads
data/sales.csvworks when you run it from~/cli-practice. Started from your home directory, the same script fails with "No such file or directory." Nothing was deleted. What happened, and what are two ways to fix it?Show answer
data/sales.csvis a relative path, so it is resolved from the working directory — from home it means~/data/sales.csv, which doesn't exist. Eithercd ~/cli-practicefirst, or use a path that means the same place from anywhere, such as~/cli-practice/data/sales.csv. See Navigating the filesystem. -
A nightly job finishes with
echo "2026-06-21 run ok" > run.log, with the date changing each night. After thirty nights, how many lines doesrun.loghold, and why?Show answer
One — last night's.
>overwrites the file every time it runs, so each night erases the history before writing its line; the log needed>>, which appends. See Pipes & redirection. -
A partner sends an 8 GB CSV that your spreadsheet app refuses to open. What are your first two commands, and what does each one tell you?
Show answer
head -n 5 file.csvshows the header and a few rows instantly, because it reads only the top of the file instead of loading all of it;wc -l file.csvcounts the lines, which is your row count (minus one for the header). Columns and size are the first things to know about any new dataset. See Looking inside files. -
Using the
data/sales.csvfrom this chapter, write one line that prints only the amounts for2026-06-02. What exactly does it print?Show answer
grep "2026-06-02" data/sales.csv | cut -d, -f3prints200then95.grepkeeps the matching rows (theWHERE), the pipe hands them tocut, andcutkeeps the third comma-separated field (theSELECT); the header never matches, so there is nothing to skip. See A taste of data wrangling. -
The chapter counts US rows with
grep ",us,". Next month the file gains rows for a new region,aus, and a colleague simplifies the pattern togrep "us". What happens to the US count, and why?Show answer
It becomes too high:
grepmatches text anywhere in the line, andauscontainsus, so every Australian row is counted as US. The commas pin the match to a whole field. It is a small case of a general rule — shell tools see lines of text, not columns, so you have to tell them where a value starts and ends. See A taste of data wrangling. -
A teammate tidies the team's export folder every Friday by dragging files around in a file manager, and says the shell would be overkill. When are they right, and what would make you insist on a command instead?
Show answer
For a genuine one-off on their own laptop, clicking is fine. What decides it is repetition, reach and scale: a weekly task should be a saved command, because text can be versioned and re-run identically while clicks can't; a server or container has no GUI at all; and thousands of files are one line in the shell but an afternoon of dragging. A Friday ritual already fails the first test. See Why the command line.
Exercise — Answer three questions about a file using only the shell
Using the data/sales.csv you created: (1) how many data rows are there (excluding the header)? (2) How many are from the eu region? (3) Save just the EU rows to data/eu.csv.
# 1) data rows = total lines minus the header
tail -n +2 data/sales.csv | wc -l # -> 4
# 2) count EU rows
grep ",eu," data/sales.csv | wc -l # -> 2
# 3) save EU rows to a new file
grep ",eu," data/sales.csv > data/eu.csv
cat data/eu.csv # confirmIf you reached for grep and a pipe instinctively, the core skill has landed. Everything else is vocabulary you'll pick up as you need it.
Takeaway
- A command is a program, flags that change its behavior, and arguments it acts on. The shell only reads the line and runs it.
- Relative paths start at the working directory and absolute paths start at the root, so run pwd before any command that changes files.
- rm has no undo, so read the path before you press Enter and never run rm -rf on a path you have not checked.
- A pipe feeds one command's output into the next, which lets small single-purpose tools do what no single app does. Data pipelines use the same idea.
- head, tail and wc -l let you meet a multi-gigabyte file without opening it.
- A saved command is repeatable and reviewable; clicking is not, which is why platform work lives in the shell.
Now make every change you type tracked and reversible with version control. → Git & GitHub
Further reading
- Shell Command Language — The Open Group, POSIX.1-2017. The standard that defines pipes, redirection and quoting across sh-compatible shells.
- POSIX Utilities — The Open Group, POSIX.1-2017. The portable behavior of ls, cp, mv, head, tail, wc, grep and cut.
- grep(1) — Linux man-pages project. Every grep option, including the recursive search used in the survival kit.
- Bash Reference Manual — GNU Project. The full reference for pipelines, redirection and history in bash.