_____ _ ___ _________ __ |_ _|__ _ __ _ __ ___ (_)_ __ __ _| \ \ / / ____\ \/ / | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | |\ \ / /| _| \ / | | __/ | | | | | | | | | | | (_| | | \ V / | |___ / \ |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_| \_/ |_____/_/\_\
grep (Global Regular Expression Print) is one of the most fundamental and powerful tools for text searching in Unix and Linux systems. It is used to find lines matching a specific pattern within file contents or command outputs. Its name comes from the g/re/p command in the ed editor, which means "globally search for a regular expression and print matching lines."
grep holds an indispensable place in the daily workflow of virtually everyone from system administrators to software developers, data analysts to security specialists. It is used in many different scenarios such as searching for errors in log files, finding a specific function in source code, or filtering large datasets. As one of the most fundamental terminal tools, grep reveals its true power when combined with the pipe mechanism.
The simplest usage of the grep command is as follows:
# Basic syntax
$ grep "search_text" filename
# Example: search for "error" in a file
$ grep "error" log.txt
# Search in multiple files
$ grep "error" log1.txt log2.txt log3.txt
# Search in all .txt files
$ grep "error" *.txt
The commands above print all lines containing the word "error" in the specified files. The matching portion is shown in color by default. grep is case-sensitive; meaning "error" and "Error" are treated differently.
Performs the search without distinguishing between uppercase and lowercase letters. This is especially useful when searching for errors in log files because they may be written as "Error", "ERROR", or "error".
# Search regardless of case
$ grep -i "error" log.txt
# Finds "error", "Error", "ERROR", "eRrOr" — all of them
Searches through all files in the specified directory and its subdirectories. This is extremely useful for finding a specific text in large projects.
# Search recursively in current directory and subdirectories
$ grep -r "TODO" .
# Recursive search in a specific directory
$ grep -r "function" /home/user/project/src/
# Recursive search in specific file types
$ grep -r --include="*.js" "console.log" .
Displays the line number of each matching line within the file. This is ideal for finding the exact location of an error or searched text when working with code.
# Search with line numbers
$ grep -n "main" program.c
# Output: 12:int main(int argc, char *argv[]) {
Shows lines that do NOT match the specified pattern. This is very useful for filtering operations.
# Show lines that don't contain "debug"
$ grep -v "debug" app.log
# Exclude comment lines
$ grep -v "^#" config.conf
# Exclude empty lines
$ grep -v "^$" file.txt
Returns the number of matching lines. Useful when you only want to know how many lines match rather than viewing the lines themselves.
# How many lines contain "warning"?
$ grep -c "warning" server.log
# Output: 47
Lists only the names of files that contain matches, without showing line contents. Ideal for quickly seeing which files contain the relevant text when searching across multiple files.
# Which files contain the word "password"?
$ grep -l "password" *.conf
# List file names recursively
$ grep -rl "deprecated" src/
The true power of grep emerges when combined with regular expressions. Regular expressions provide a special syntax for defining text patterns.
# Lines starting with "Error" at the beginning
$ grep "^Error" log.txt
# Lines ending with "failed"
$ grep "failed$" log.txt
# Match any single character (.)
$ grep "h.t" file.txt # matches hat, hot, hit, hut, etc.
# One or more repetitions (+) — use egrep or grep -E
$ grep -E "go+d" file.txt # god, good, goood, etc.
# Match one of specific characters ([])
$ grep "[aeiou]" file.txt # Lines containing vowels
# Lines containing digits
$ grep "[0-9]" file.txt
# Search for IP address format
$ grep -E "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" access.log
# Search for email format
$ grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}" contacts.txt
When used with the pipe (|) operator, grep becomes a perfect tool for filtering the output of other commands. This is one of the finest examples of the Unix philosophy.
# Search running processes
$ ps aux | grep "nginx"
# Filter network connections
$ netstat -an | grep ":80"
# Search command history
$ history | grep "git commit"
# Chain filtering with multiple greps
$ cat access.log | grep "POST" | grep "api" | grep -v "health"
# Find specific directory in disk usage
$ df -h | grep "/home"
# Search environment variables
$ env | grep "PATH"
egrep is the version of grep that supports extended regular expressions and is equivalent to grep -E. fgrep performs fixed-string searches (no regex interpretation) and is equivalent to grep -F.
# Using OR operator with egrep
$ egrep "error|warning|critical" log.txt
# or
$ grep -E "error|warning|critical" log.txt
# Searching special characters literally with fgrep
$ fgrep "price=$10.00" data.txt
# or
$ grep -F "price=$10.00" data.txt
# Find errors in the last 1000 lines
$ tail -1000 /var/log/syslog | grep -i "error"
# Find errors in a specific date range
$ grep "2026-02-14" app.log | grep -i "error"
# Show lines before and after the error (context)
$ grep -B 3 -A 3 "Exception" app.log
# Count unique error messages
$ grep -i "error" app.log | sort | uniq -c | sort -rn
# Finding unused functions in a project
$ grep -rn "function oldMethod" src/
# Listing TODO and FIXME comments
$ grep -rn -E "(TODO|FIXME|HACK|XXX)" src/
# Finding files that use a specific import
$ grep -rl "import.*React" src/ --include="*.tsx"
-F for fixed-string searches: Disabling the regex engine speeds up the search significantly.--include: Save time by skipping unnecessary files.-I flag automatically skips binary files.-m for large files: Stops the search after a specified number of matches.ripgrep (rg) as an alternative: It runs much faster than grep on very large codebases.grep is the most fundamental and powerful text search tool in the terminal world. It covers a wide range of uses from simple text searches to complex regular expressions, from log analysis to code scanning. Learning flags such as -i, -r, -n, -v, -c, and -l will greatly speed up your daily workflow. When combined with the pipe mechanism, it offers virtually unlimited filtering and searching power. Using grep effectively is one of the most important building blocks of your terminal mastery.