Quick take: The grep command searches text for lines matching a pattern. Use -i to ignore case, -r to search directories recursively, -n to show line numbers, and -E for extended regular expressions.

Introduction

The grep command (global regular expression print) searches files or input for lines that match a pattern and prints them. It is the workhorse of text searching in Linux — finding a setting in a config file, a message in a log, or every occurrence of a function across a codebase.

This guide covers everyday grep usage, the options you will use most, and how regular expressions unlock far more powerful searches.

Syntax

The basic syntax of the grep command is:

grep [OPTIONS] PATTERN [FILE...]

Using grep with Regular Expressions

grep's real power is regular expressions. With basic regex you can anchor matches and use character classes; with -E (extended regex) you get alternation and quantifiers without backslashes.

# Lines starting with 'ERROR'
grep '^ERROR' app.log

# Lines ending with a semicolon
grep ';$' code.c

# IP-like pattern (extended regex)
grep -E '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' access.log

Use -o to print only the matched portion, which is perfect for extracting values rather than whole lines.

Common Options and Parameters

The most useful options and parameters for the grep command:

OptionDescription
-iIgnore case when matching.
-r, -RSearch recursively through directories.
-nShow the line number of each match.
-cCount matching lines instead of printing them.
-lPrint only the names of files that contain a match.
-vInvert — show lines that do NOT match.
-wMatch whole words only.
-oPrint only the matched part of the line.
-EExtended regex (enables +, ?, |, () without backslashes).
-FFixed strings — treat the pattern literally, not as a regex.
-A nPrint n lines of context after each match.
-B nPrint n lines of context before each match.
-C nPrint n lines of context around each match.
--color=autoHighlight the matched text.

Practical Examples

Real grep commands you can run today:

# Search for a word in a file
grep 'error' app.log
# Case-insensitive search
grep -i 'warning' app.log
# Recursive search through a directory
grep -rn 'TODO' ./src
# Show only matching file names
grep -rl 'api_key' /etc
# Count how many lines match
grep -c 'GET' access.log
# Invert: lines that do NOT contain '#'
grep -v '^#' config.conf
# Show 3 lines of context around matches
grep -C 3 'panic' kernel.log
# Extended regex: match foo or bar
grep -E 'foo|bar' data.txt

grep in Pipelines and Real Workflows

grep is most powerful as a filter in a pipeline, narrowing the output of other commands. This is how administrators find a process, a port, or a setting buried in noisy output.

# Is nginx running?
ps aux | grep [n]ginx

# Which package owns a command (Debian/Ubuntu)
dpkg -l | grep openssh

# Count 404s in a web log
grep -c ' 404 ' access.log

# Show unique IP addresses that hit an endpoint
grep '/login' access.log | awk '{print $1}' | sort -u

The [n]ginx trick is worth knowing: the bracket stops grep from matching its own process line, a classic annoyance when grepping ps output.

Common grep Mistakes

The most frequent confusion is regex versus literal text. By default grep treats the pattern as a basic regular expression, so characters like ., *, and [ are special. If you are searching for a literal string that contains them — an IP address or a file path — use -F (fixed strings) so they are matched verbatim.

A second mistake is forgetting to quote the pattern. Without quotes the shell may expand * or ? before grep ever sees them. Always wrap patterns in single quotes, and remember that -w (whole word) prevents partial matches like cat inside concatenate.

Tips and Best Practices

  • Combine flags: grep -rin 'pattern' . searches recursively, case-insensitively, with line numbers — the search you will run most.
  • Use -F (fixed strings) when your search text contains regex characters like . or * that you want treated literally.
  • Pipe other commands into grep to filter their output, e.g. ps aux | grep nginx.

Final Thoughts

grep is the first tool to reach for whenever you need to find text. Learn the core flags — -i, -r, -n, -v, -c — and a little regular-expression syntax, and you can search any file, log, or codebase in seconds. It pairs naturally with pipes, find, and sed.

Linux grep quick reference

Search one file with grep 'error' app.log, ignore case with -i, show line numbers with -n, and search a directory recursively with -R. Use -E for extended regular expressions, -F when the pattern should be treated as fixed text, and -C 3 to show three context lines around each match.

Quote patterns containing spaces or shell characters. Limit large searches with --include and --exclude-dir, and avoid printing secrets from production logs into shared terminals or tickets. Combine grep with the find command when file selection depends on size, ownership, or modification time.

FAQ: grep Command in Linux

How do I search for text in a file with grep?+

Run grep 'pattern' filename. Add -i to ignore case and -n to show line numbers. For a directory, add -r to search recursively.

How do I search recursively through directories?+

Use grep -r 'pattern' /path, or grep -rn to include line numbers and grep -rl to list only the matching file names.

How do I show lines that do NOT match?+

Use the -v flag: grep -v 'pattern' file prints every line except those containing the pattern. It is great for stripping comments with grep -v '^#'.

How do I match whole words only?+

Use -w: grep -w 'cat' file matches the word cat but not 'category' or 'concatenate'.

What is the difference between grep, egrep, and grep -E?+

egrep is the old name for extended-regex grep and is now deprecated in favour of grep -E, which enables +, ?, |, and () without backslashes. They behave the same; prefer grep -E.

Need help with Linux servers or infrastructure?

Work directly with Muhammad Irfan Aslam for Linux, Ubuntu, Docker, DevOps, cloud, CI/CD, or infrastructure support.

Hire Me for Support