Skip to content

How to Recursively Search Files with grep

DodaTech 2 min read

In this tutorial, you'll learn about How to Recursively Search Files with grep. We cover key concepts, practical examples, and best practices.

The Problem

You need to find where a function is called or a config value is set across an entire project. Opening each file manually is impractical for projects with hundreds of files. The grep -r command searches recursively through directories, matching text patterns in file contents. With the right flags, you can filter by file type, show context lines, exclude directories, and even count matches per file.

Quick Fix

1. Recursive search in current directory

grep -r "function_name" .

Expected output:

./src/app.js:10:function function_name() {
./src/utils.js:45:const result = function_name(input);
./tests/test_app.js:23:function_name.mock.calls.length

The output shows the file path, line number, and matched line content.

2. Search with case-insensitive and whole-word flags

grep -riw "TimeoutError" src/

-r is recursive, -i is case-insensitive, -w matches whole words only. Without -w, TimeoutError would also match TimeoutErrorHandler.

3. Filter by file type (--include)

grep -r --include="*.py" "def test_" tests/

grep -r --include="*.{js,ts}" "import React" src/

--include limits the search to files matching the glob pattern. Multiple patterns can be combined with braces.

4. Exclude files or directories

grep -r "api_key" . --exclude-dir=node_modules --exclude-dir=.git

grep -r "password" . --exclude="*.min.js" --exclude-dir=vendor

Use --exclude-dir to skip entire directories and --exclude to skip file patterns. Always exclude node_modules, .git, and vendor for speed.

5. Show context around matches

# Show 2 lines before and after each match
grep -r -C 2 "TODO" .

# Show only lines before
grep -r -B 3 "FIXME" .

# Show only lines after
grep -r -A 5 "import" src/

Context makes results readable, especially for understanding the surrounding code.

6. Show only filenames that match (-l)

grep -rl "express" . --include="*.json"

Expected output:

./package.json
./package-lock.json

The -l flag lists only filenames, not the matching lines. Useful for counting or piping to other commands.

7. Count matches per file

grep -rc "console.log" src/

Expected output:

src/app.js:12
src/utils.js:3
src/db.js:0

8. Search for multiple patterns

grep -r -e "ERROR" -e "FATAL" /var/log/

The -e flag specifies a pattern. Multiple -e flags act as OR conditions.

9. Search binary files and device files

# Search only binary files (default skips them)
grep -ra "pattern" /usr/bin/

# Search without ignoring binary
grep -r --binary-files=text "pattern" /var/log/

Use -a to treat binaries as text when searching log files or executables for embedded strings.

Prevention

  • Always use --exclude-dir=.git and --exclude-dir=node_modules for project searches
  • Use -l (list files) first to understand the scope before reading details
  • Use -n to show line numbers — it's on by default with -r in most grep versions
  • Prefer grep -r over grep -R (which follows symlinks and may create duplicates)
  • Use rg (ripgrep) for faster searches on very large repositories
  • Use -a when searching binary files for embedded strings or log patterns

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro