grep: search inside files
grep prints the lines of a file that contain a word or pattern. It answers "where does this appear?" for one file or ten thousand. It reads and never changes anything.
The basic search
asha@pc:~/demo$ grep ERROR log.txt
09:05 ERROR Printer not found
09:07 ERROR Printer not foundThe pattern comes first, then the file.
The everyday options
| Option | Effect |
|---|---|
-i | ignore capital and small letters |
-n | show line numbers |
-c | count matching lines |
-v | invert: show lines that do not match |
-w | match whole words only |
-l | list only the names of files that contain a match |
-r | search all files in a folder and below |
-A 2, -B 2 | also show 2 lines after, or before, each match |
-E | extended patterns, such as a|b for either |
asha@pc:~/demo$ grep -n -i printer log.txt
3:09:05 ERROR Printer not found
5:09:07 ERROR Printer not found
asha@pc:~/demo$ grep -c ERROR log.txt
2
asha@pc:~/demo$ grep -v INFO log.txt
09:05 ERROR Printer not found
09:07 ERROR Printer not found
09:10 WARN Low disk spaceA phrase
A pattern with spaces needs quotation marks.
asha@pc:~/demo$ grep "Low disk" log.txt
09:10 WARN Low disk spaceSeveral files
Give several names or a wildcard. Each match is shown with its file name.
asha@pc:~/demo$ grep -i report *.txt
log.txt:09:02 INFO Opened report.txt
log.txt:09:15 INFO Saved report.txt
report.txt:Sales report for OctoberA whole folder
-r searches every file below a folder. Adding -l gives just the file names, and -n the line numbers.
asha@pc:~/demo$ grep -r -l -i report .
./log.txt
./old/draft.txt
./report.txt
asha@pc:~/demo$ grep -rn "draft" .
./old/draft.txt:1:First draft of the reportThe dot means "the current folder". Limit the search to certain files with --include:
asha@pc:~/demo$ grep -rn --include="*.txt" -i total .
./report.txt:5:Total: 18700Whole words
Without -w, the pattern matches anywhere, even inside longer words.
asha@pc:~/demo$ grep -c port log.txt
2
asha@pc:~/demo$ grep -c -w port log.txt
0The first counts lines containing "port", which includes "report". The second counts only the word by itself.
Either of two words
-E switches on extended patterns, where a bar means "or".
asha@pc:~/demo$ grep -E "ERROR|WARN" log.txt
09:05 ERROR Printer not found
09:07 ERROR Printer not found
09:10 WARN Low disk spaceContext
When a match alone is not enough, show the lines around it.
asha@pc:~/demo$ grep -A 1 ERROR log.txt
09:05 ERROR Printer not found
09:06 INFO Retrying
09:07 ERROR Printer not found
09:10 WARN Low disk spacePatterns
grep understands regular expressions. The most useful pieces:
| Pattern | Matches |
|---|---|
^word | lines that start with word |
word$ | lines that end with word |
. | any one character |
[0-9] | any digit |
[A-Z] | any capital letter |
a* | a repeated none or more times |
^$ | empty lines |
asha@pc:~/demo$ grep "^09:0" log.txt
09:00 INFO Program started
09:02 INFO Opened report.txt
09:05 ERROR Printer not found
09:06 INFO Retrying
09:07 ERROR Printer not found
asha@pc:~/demo$ grep "closed$" log.txt
09:16 INFO Program closed
asha@pc:~/demo$ grep -c "^[A-Z]" marks.csv
5Put patterns in quotation marks, so that the shell does not try to interpret the special characters itself. To search for text that contains these characters literally, use -F, for fixed text: grep -F "a.b" file.
Searching the output of other commands
grep reads from a pipe as well as from files. This is how it is used most.
asha@pc:~/demo$ ls -l | grep csv
-rw-r--r-- 1 asha asha 53 Nov 1 15:00 marks.csvCommon uses: ps aux | grep firefox to find a running program, history | grep ssh to find an earlier command, and dmesg | grep -i usb to look at system messages.
Counting and combining
-c counts lines. To count matches in many files and total them, pipe through wc -l.
asha@pc:~/demo$ grep -h ERROR log.txt | wc -l
2Saving the result
asha@pc:~/demo$ grep ERROR log.txt > errors.txt
asha@pc:~/demo$ cat errors.txt
09:05 ERROR Printer not found
09:07 ERROR Printer not foundSpeed and binary files
grep is fast. On very large folders, exclude what you do not need with --exclude-dir, such as --exclude-dir=.git. If it reports "Binary file matches", the file is not text. -I skips such files.
Common mistakes
- The file and pattern the wrong way round. Pattern first.
- No quotation marks round a pattern with spaces or symbols.
- Forgetting
-iand missing "Error" while searching for "error". - Forgetting
-rwhen pointing at a folder: "Is a directory". - A search that hangs. With no file named,
grepwaits for you to type input. Press Ctrl + C.
The Windows equivalent is findstr.
Examples shown with output were run on 12 November 2026 in a practice folder: Windows commands in cmd.exe on Windows 11, Linux commands with the GNU tools of Git Bash. The folder path and user name were replaced with made-up ones. Commands marked "not run here" are shown as you would type them.
This is an independent learning site. It is not connected with Microsoft, Apple or any Linux distribution. Windows, macOS and other names belong to their owners. Try commands first in a practice folder, never on files you cannot afford to lose.