<aside> 🔍

Module 6 — Finding Things: find and grep

Two questions dominate real operations work: where is the file? and which files contain this? find answers the first by walking the tree; grep answers the second by reading contents. Between them sits the skill interviewers probe hardest — regular expressions. This module goes deep on all three; its sibling, Module 7, does the same for editing text.

Legend used throughout: 🧠 concept → 🧩 analogy → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (hidden)

</aside>

<aside> 🚦

Before you start

You need Modules Module 1 — What Linux Is–Module 5 — The Shell, Properly — pipes, exit codes, quoting, and globbing are load-bearing here. Build the playground by pasting this whole block (the cat > file <<'EOF' construct collects the lines you paste, until the EOF line, into the file — a Module 10 construct on early loan):

mkdir -p ~/search/app/logs ~/search/app/config ~/search/notes
cd ~/search
cat > app/logs/app.log <<'EOF'
2026-09-02 10:00:01 INFO  Service starting
2026-09-02 10:00:02 INFO  Config loaded from /etc/app/app.conf
2026-09-02 10:03:15 WARN  Slow response from db-01 (1200ms)
2026-09-02 10:04:44 ERROR Connection to db-01 refused
2026-09-02 10:04:45 ERROR Retry 1 failed: connection refused
2026-09-02 10:04:47 error retry 2 failed: connection refused
2026-09-02 10:05:00 INFO  Failover to db-02
2026-09-02 10:05:01 INFO  Connection to db-02 established
EOF
cat > app/config/app.conf <<'EOF'
listen_port=8080
db_host=db-01
db_port=5432
# temporary override
db_host_backup=db-02
EOF
echo 'remember: rotate keys' > notes/todo.txt
touch -d '2 days ago' notes/old.txt

</aside>

<aside> ℹ️

This page uses Mermaid diagram blocks. Notion shows them as code by default — click the block and set it to Preview to see the diagram. This reminder appears once per page.

</aside>

Part A — grep: reading for you

A1. grep fundamentals

<aside> 📖

Official docs: grep(1) — print lines that match patterns

</aside>

🧠 grep pattern file prints every line containing a match for the pattern. The daily options: -i ignore case, -n show line numbers, -c count matching lines instead of printing them, -w match whole words only. And one behaviour that matters enormously to automation: grep's exit code speaks (Module 5): 0 — found something; 1 — found nothing (not an error!); 2 — actual trouble (unreadable file). "No matches" being exit 1 makes grep a test you can build conditions on — and a trap inside strict scripts, revisited in this module's tickets.

<aside> 🧩

Real-world analogy — the assistant with the highlighter

Hand an assistant a 400-page transcript: "copy out every line that mentions the defendant". Back comes one tidy page of quotes. grep is that assistant — tireless, literal, and done in milliseconds.

Where the analogy stops working. A human assistant copies the surrounding sentences when a quote would mislead alone. grep copies exactly the matching lines and nothing else — context is lost unless you explicitly ask for it (A4), and a match mid-word is still a match unless you say -w.

</aside>

🧪 Exercise A1.1 — First reads of a real log

cd ~/search
grep ERROR app/logs/app.log
grep -i error app/logs/app.log      # case-insensitive: catches the sloppy lowercase line
grep -c -i error app/logs/app.log   # just the count
grep -n refused app/logs/app.log    # with line numbers

A2. -v and grep as a pipeline filter

<aside> 📖

Official docs: grep(1)

</aside>

🧠 -v inverts: print lines that do not match. And because grep reads stdin when given no file, it slots into Module 5's pipelines as the universal filter: command | grep pattern | grep -v noise. Include-then-exclude chains read like sentences: "lines about the db, but not the healthy ones".

<aside> 🧩

Real-world analogy — the two-door screening

Airport security in two stages: the first door admits only ticket-holders (include), the second pulls aside anyone on the fast-track list (exclude). Chaining greps is stacking doors; each stage sees only what the previous one passed.

Where the analogy stops working. Doors screen people one at a time in order of arrival; a grep chain preserves line order but each stage is a separate process running concurrently (Module 5's pipes) — the second door is already screening while the first is still admitting. Also: -v rejects whole lines — there is no "remove just the bad word", which is Module 7's job (sed).

</aside>

🧪 Exercise A2.1 — Sculpt the log down to the incident

cd ~/search
grep -v INFO app/logs/app.log                    # drop the routine chatter
grep -i error app/logs/app.log | grep -v Retry   # errors, but not the retries
env | grep -i home                               # filter ANY command's output

A3. -r and -l — searching whole trees