grep: finding lines

grep, sed & awk · Essentials · 10 min

grep is the fastest way to find where something is mentioned, in one file or across a whole project.

grep PATTERN [FILE...] prints every line containing a match for PATTERN. With no file it reads standard input, so it works at the end of any pipeline. Quote the pattern in single quotes so the shell leaves it alone.

The flags you'll use daily:

  • -i ignore case; -v invert: print lines that do not match.
  • -n prefix line numbers; -c print only the count of matching lines.
  • -w match whole words only, so -w cat skips concatenate.
  • -l list only the names of files that contain a match.
  • -r search a directory tree recursively (-R also follows symlinks).
  • -e PAT adds a pattern (repeatable, also needed for patterns starting with -).

When several files are searched, grep prefixes each line with the file name; -h hides it and -H forces it. With -r, narrow the search with --include='*.py', --exclude='*.min.js' and --exclude-dir=node_modules.

By default the pattern is a basic regular expression, so characters such as . and * are special. If you are searching for a literal string, use -F (fixed strings): it is faster and you can't be surprised by a stray dot.

Flags combine freely: grep -rniw todo src/ finds TODOs, any case, as whole words, with file names and line numbers.

Example

printf 'apple pie\nbanana split\nApple tart\ncherry pie\n' > menu.txt

grep apple menu.txt          # apple pie
grep -i apple menu.txt       # apple pie / Apple tart
grep -v pie menu.txt         # banana split / Apple tart
grep -c pie menu.txt         # 2
grep -n cherry menu.txt      # 4:cherry pie
grep -F 'pie' menu.txt       # literal search, no regex meaning

# recursive search in a project, only Python files, skipping a directory
grep -rn --include='*.py' --exclude-dir=.venv 'import requests' .
grep -rl 'TODO' src/         # just the file names

Remember

  • -i ignore case, -v invert, -n line numbers, -c count, -w whole word
  • -r searches directories; narrow it with --include and --exclude-dir
  • -F treats the pattern as a plain string: faster and no regex surprises

Watch out for

  • Forgetting to quote the pattern, so the shell expands * or splits words before grep sees them.

Check yourself

  1. What does grep -vc error app.log print?
  2. Why use grep -F '1.5.0' instead of grep '1.5.0'?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.gnu.org/software/grep/manual/grep.html#Invoking