Search Files for Text with grep
grep is one of the most useful commands in Linux — and most people only know 10% of what it can do.
This script searches every file in a folder for a keyword and shows you the exact filename and line number
for every match. Perfect for hunting down TODOs, finding config values, or searching your own project files.
The Script
Paste this into search.sh. Change SEARCH_DIR, KEYWORD, and the --include file type to match what you're looking for.
#!/bin/bash # Search Files for Text (grep) # Searches all .txt files in a folder for a keyword. # Shows filename and line number for each match. # # USAGE: ./search.sh # REQUIRES: bash, grep (pre-installed on all Linux/macOS) SEARCH_DIR="$HOME/documents" # ← folder to search inside KEYWORD="TODO" # ← word or phrase to find FILE_TYPE="*.txt" # ← file extension to search echo "Searching for '$KEYWORD' in $SEARCH_DIR..." echo "---" grep -rn "$KEYWORD" "$SEARCH_DIR" --include="$FILE_TYPE" echo "---" echo "✓ Done."
grep -rn searches recursively through all subfolders (-r) and includes line numbers in results (-n). "$KEYWORD" is the word or phrase to find. "$SEARCH_DIR" is the folder to search inside. --include="$FILE_TYPE" limits the search to files matching that pattern — without it, grep searches every file including binaries.
Step-by-Step Setup
Step 1 — Create the file
nano search.sh
Paste the script, then Ctrl+X → Y → Enter to save.
Step 2 — Set your variables
| Variable | Example | What it means |
|---|---|---|
| SEARCH_DIR | $HOME/documents | The folder (and all subfolders) to search inside |
| SEARCH_DIR | /var/www/html | A web project directory |
| KEYWORD | TODO | Finds every line containing the word TODO |
| KEYWORD | api_key | Hunts for hardcoded secrets across your project |
| FILE_TYPE | *.txt | Search only plain text files |
| FILE_TYPE | *.py | Search only Python files |
| FILE_TYPE | *.sh | Search only bash scripts |
| FILE_TYPE | *.js | Search only JavaScript files |
Step 3 — Make it executable and run
chmod +x search.sh ./search.sh
Searching for 'TODO' in /home/user/documents...
---
/home/user/documents/notes.txt:14: TODO: fix the login bug
/home/user/documents/project.txt:3: TODO: add error handling
---
✓ Done.
Variations
Run it as a one-liner without a script
For quick one-off searches you don't need a script at all. Just run directly in the terminal:
# Search all .sh files for the word "error" grep -rn "error" ~/scripts --include="*.sh" # Search ALL file types (no filter) grep -rn "TODO" ~/myproject
Case-insensitive search
Add -i to match regardless of capitalisation — finds TODO, todo, Todo all at once:
#!/bin/bash SEARCH_DIR="$HOME/documents" KEYWORD="todo" grep -rni "$KEYWORD" "$SEARCH_DIR" --include="*.txt"
Show only filenames, not the matching lines
Add -l to get just a list of files that contain the keyword — useful when you have many matches:
#!/bin/bash SEARCH_DIR="$HOME/documents" KEYWORD="TODO" # -l = show only filenames, not the matching lines grep -rl "$KEYWORD" "$SEARCH_DIR" --include="*.txt"
Count how many matches are in each file
#!/bin/bash SEARCH_DIR="$HOME/myproject" KEYWORD="TODO" # -c = count of matches per file grep -rc "$KEYWORD" "$SEARCH_DIR" --include="*.py" \ | grep -v ":0" # hide files with zero matches
Search for multiple keywords at once
#!/bin/bash SEARCH_DIR="$HOME/myproject" # -e lets you pass multiple patterns grep -rn -e "TODO" -e "FIXME" -e "HACK" "$SEARCH_DIR" \ --include="*.py"
Search and save results to a file
#!/bin/bash SEARCH_DIR="$HOME/myproject" KEYWORD="TODO" OUTPUT="$HOME/todo-list.txt" grep -rn "$KEYWORD" "$SEARCH_DIR" --include="*.py" > "$OUTPUT" echo "✓ Results saved to $OUTPUT"
Common Mistakes
Without --include, grep searches every file including compiled binaries and image files. This produces garbage output and slows things down. Always specify a file type unless you intentionally want to search everything.
If your keyword contains characters like ., *, [, or (, grep treats them as regex. To search for them literally, add -F (fixed string mode): grep -rn -F "error()" ~/project
If grep returns hundreds of matches, add -l to see just the filenames first, then open the specific file. Or use -m 5 to limit output to the first 5 matches per file.
grep Flag Cheat Sheet
| Flag | What it does | Example |
|---|---|---|
| -r | Search recursively through subfolders | grep -r "word" ~/folder |
| -n | Show line number with each match | grep -n "word" file.txt |
| -i | Case-insensitive matching | grep -ri "word" ~/folder |
| -l | Show filenames only, not the matching lines | grep -rl "word" ~/folder |
| -c | Count matches per file | grep -rc "word" ~/folder |
| -v | Invert — show lines that do NOT match | grep -v "word" file.txt |
| -F | Treat keyword as plain string, not regex | grep -rF "error()" ~/folder |
| -m 5 | Stop after 5 matches per file | grep -rn -m 5 "word" ~/folder |
| --include | Limit to files matching a pattern | grep -rn "word" ~/folder --include="*.py" |
| --exclude | Skip files matching a pattern | grep -rn "word" ~/folder --exclude="*.log" |
Frequently Asked Questions
How do I search all files in a folder for a word in Linux?
Use grep -rn 'keyword' /path/to/folder to search recursively. Add --include='*.txt' to limit the search to specific file types. The -n flag shows the line number alongside each match.
What does grep -rn do?
-r makes grep search recursively through all subfolders. -n includes the line number in every result. Together they give you: filename, line number, and the matching line — everything you need to find and act on a match fast.
How do I search only specific file types with grep?
Add the --include flag: grep -rn 'keyword' /folder --include='*.py' searches only Python files. Use *.sh for shell scripts, *.js for JavaScript, and so on.
How do I make grep case insensitive?
Add -i: grep -rni 'keyword' /folder matches any capitalisation of the keyword. Useful when you're not sure how a term appears across different files.