datarekha

Searching with grep

Learn to search file contents with grep — the fastest way to find which files contain a pattern, on what line, and in what context.

8 min read Beginner Command Line Lesson 5 of 14

What you'll learn

  • Run grep to find lines matching a pattern in one file or an entire directory tree
  • Use essential flags: -i, -r, -n, -w, -v, -c, -l, -o, and -A/-B/-C
  • Pass grep a piped stream and write basic regex patterns with -E

Before you start

What grep does

grep reads lines of text and prints only the ones that match a pattern — a string or a regular expression you supply. Think of it as a filter: every line goes in, only matching lines come out.

input lines ──► [ grep PATTERN ] ──► matching lines
all lines(input)grep PATTERN(filter)matching lines(output)
grep passes only lines that match your pattern

Basic syntax

grep PATTERN file

Search config.py for the string API_KEY:

grep API_KEY config.py
API_KEY = "abc123"

You can search multiple files at once by listing them or using a glob:

grep API_KEY config.py settings.py
grep API_KEY *.py

Essential flags

-n — show line numbers

Tells you exactly where the match lives. Almost always useful.

grep -n API_KEY config.py
14:API_KEY = "abc123"

-i — case-insensitive

Matches api_key, API_KEY, Api_Key, etc.

grep -i api_key config.py

-r / -R — recursive through a directory

This is the answer to the opening question. Search every file under src/:

grep -r API_KEY src/
src/config.py:14:API_KEY = "abc123"
src/utils/auth.py:3:API_KEY = os.environ.get("API_KEY")

-r follows symbolic links on most systems; -R always does on GNU grep.

-l — list filenames only

When you only need to know which files match, not the lines themselves:

grep -rl API_KEY src/
src/config.py
src/utils/auth.py

-c — count matching lines per file

grep -rc API_KEY src/
src/config.py:1
src/utils/auth.py:1
src/tests/test_auth.py:0

-w — whole word

Without -w, grep error matches errors, errored, and fatal_error. With -w it only matches the standalone word error.

grep -w error app.log

-v — invert (lines that do NOT match)

Invert flips the filter: print every line that does not match the pattern. Handy for stripping comments or blank lines.

grep -v "^#" config.ini

That ^# is a tiny regex — ^ anchors to the start of the line, so this removes lines that begin with #.

-o — print only the matching part

Instead of the whole line, emit just the text that matched:

grep -o "API_KEY" config.py
API_KEY

More useful combined with regex (shown below).

-A, -B, -C — context lines

Real errors don’t exist in isolation. Context flags print surrounding lines so you can see what caused a match.

FlagMeaning
-A NN lines After the match
-B NN lines Before the match
-C NN lines before and after (Context)
grep -C 2 "TypeError" app.log
Traceback (most recent call last):
  File "app.py", line 42, in process
    result = int(value)
TypeError: int() argument must be a string
During handling of the above exception:

Reading from a pipe

grep works seamlessly in a pipeline. The command to the left produces lines; grep filters them.

ps aux | grep nginx
root      1234  0.0  nginx: master process
www-data  1235  0.1  nginx: worker process
cat app.log | grep -i "error"

You can chain multiple greps to narrow results further:

grep -r "def " src/ | grep -v "test_"

This finds all function definitions except those in test files.

A gentle intro to regex in grep

grep patterns are regular expressions — a mini-language for describing text shapes. You don’t need to learn all of it now. Here are the most useful pieces:

PatternMatches
.any single character
^foolines that start with foo
foo$lines that end with foo
[aeiou]any one vowel
[0-9]any digit

To use extended regex (which adds +, ?, \d, \w, and more), pass -E:

grep -E "[0-9]{4}" data.txt
port: 8080
year: 2026

[0-9]{4} matches exactly four consecutive digits.

grep -E "^(ERROR|WARN)" app.log

Matches lines that begin with either ERROR or WARN.

Putting it all together

Back to the opening question — 400 files, find every mention of API_KEY with line numbers:

grep -rn API_KEY .
./src/config.py:14:API_KEY = "abc123"
./src/utils/auth.py:3:API_KEY = os.environ.get("API_KEY")
./docs/setup.md:22:export API_KEY=your_key_here

Three files, three lines, under a second. That’s grep.


Quick check

0/3
Q1Which flag prints the line number alongside each match?
Q2You want every line in error.log that does NOT contain the word 'DEBUG'. Which command is correct?
Q3A teammate asks: 'I need to search every .js file under src/ for the string fetch( and see two lines of context after each match — what single command does that?' Which answer is correct?

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Related lessons

Skip to content