Course 2 · Hands-on

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.

Setup — do this first

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:

ls -l /tmp │ │ │ │ │ └── argument (what to act on) │ └─────── option/flag (how to behave; usually starts with - ) └──────────── command (the program to run)

Why the command line (when GUIs exist)

The shell gives you…Why it matters for data work
ReachRemote servers and containers have no GUI — only a shell. This is how you operate them.
RepeatabilityA command is text you can save, version, and re-run. Clicking is not reproducible.
ComposabilitySmall tools snap together with pipes to do things no single app does.
Speed at scaleRename 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:

terminal
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 tree
✓ You should see

ls -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 has no undo

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:

terminal
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 search
Why head/tail matter

You'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).
cat sales.csv │ grep "2026" │ wc -l > count.txt │ │ │ │ read file keep matching count them save result lines only to a file ───────────────────────────────────────────────────────▶ data flows left to right
terminal
# 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.log
The Unix philosophy

Each 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.

terminal
# 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 header
✓ You should see

wc -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 / keyDoes
TabAuto-complete file/command names — use it constantly
↑ / Ctrl-RPrevious command / search command history
Ctrl-CStop the running command
Ctrl-L / clearClear the screen
man ls / ls --helpRead a command's manual / quick help
which pythonShow 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.

  1. A script that reads data/sales.csv works 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.csv is a relative path, so it is resolved from the working directory — from home it means ~/data/sales.csv, which doesn't exist. Either cd ~/cli-practice first, or use a path that means the same place from anywhere, such as ~/cli-practice/data/sales.csv. See Navigating the filesystem.

  2. 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 does run.log hold, 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.

  3. 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.csv shows 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.csv counts 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.

  4. Using the data/sales.csv from this chapter, write one line that prints only the amounts for 2026-06-02. What exactly does it print?

    Show answer

    grep "2026-06-02" data/sales.csv | cut -d, -f3 prints 200 then 95. grep keeps the matching rows (the WHERE), the pipe hands them to cut, and cut keeps the third comma-separated field (the SELECT); the header never matches, so there is nothing to skip. See A taste of data wrangling.

  5. 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 to grep "us". What happens to the US count, and why?

    Show answer

    It becomes too high: grep matches text anywhere in the line, and aus contains us, 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.

  6. 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.

solution
# 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                            # confirm

If 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.