How to Recursively Search Files with grep
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=.gitand--exclude-dir=node_modulesfor project searches - Use
-l(list files) first to understand the scope before reading details - Use
-nto show line numbers — it's on by default with-rin most grep versions - Prefer
grep -rovergrep -R(which follows symlinks and may create duplicates) - Use
rg(ripgrep) for faster searches on very large repositories - Use
-awhen searching binary files for embedded strings or log patterns
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro