Grep Command in Linux with Examples

By 

Updated on

13 min read

Grep Command in Linux

Grep is one of the most commonly used commands in Linux. The name stands for “Global Regular Expression Print”.

The grep command searches for a text pattern in one or more files and prints every line that matches. It is a powerful tool for searching and analyzing large amounts of text data quickly and efficiently. You can use it to search for specific words, phrases, or regular expressions in files of any size, from small configuration files to large log files. If no files are specified, grep reads from standard input, which is usually the output of another command.

This guide covers the most common GNU grep options with practical examples.

grep Command Syntax

The syntax for the grep command is as follows:

txt
grep [OPTIONS] PATTERN [FILE...]

The items in square brackets are optional.

  • OPTIONS - Zero or more options. Grep includes a number of options that control its behavior.
  • PATTERN - The search pattern (string or regular expression).
  • FILE - Zero or more input file names.

To search a file, the user running the command must have read access to it.

Search for a String in Files

The most basic usage of the grep command is to search for a string (text) in a file.

For instance, to find all lines containing the string “bash” in the /etc/passwd file, run the following command:

Terminal
grep bash /etc/passwd

The output shows every line that contains the matching string:

output
root:x:0:0:root:/root:/bin/bash
linuxize:x:1000:1000:linuxize:/home/linuxize:/bin/bash

If the string contains spaces, enclose it in single or double quotation marks:

Terminal
grep "Gnome Display Manager" /etc/passwd

By default, grep is case-sensitive, meaning uppercase and lowercase characters are treated as distinct.

To ignore case when searching, use the -i option (or --ignore-case).

For example, searching for “Zebra” without -i will not match lowercase entries:

Terminal
grep Zebra /usr/share/dict/words

No output is produced because there are no lines matching the exact case. If you perform a case-insensitive search using the -i option, it will match all variations:

Terminal
grep -i Zebra /usr/share/dict/words
output
zebra
zebra's
zebras

Search for Full Words

When searching for a string, grep displays all lines where the string appears, even if it is embedded in a larger word.

For example, if you search for “gnu”, grep will match lines containing “gnu” as well as words like “cygnus” or “magnum”:

Terminal
grep gnu /usr/share/dict/words
output
cygnus
gnu
interregnum
lignum
magnum
magnuson
sphagnum
wingnut

To return only lines where the specified string is a whole word (enclosed by non-word characters), use the -w option (or --word-regexp):

Terminal
grep -w gnu /usr/share/dict/words
output
gnu
Info
Word characters include alphanumeric characters (a-z, A-Z, and 0-9) and underscores (_). All other characters are considered non-word characters.

Invert Match (Exclude)

Use the -v option (or --invert-match) to display lines that do not match a pattern.

For example, to print lines that do not contain the string “nologin”:

Terminal
grep -v nologin /etc/passwd
output
root:x:0:0:root:/root:/bin/bash
colord:x:124:124::/var/lib/colord:/bin/false
git:x:994:994:git daemon user:/:/usr/bin/git-shell
linuxize:x:1000:1000:linuxize:/home/linuxize:/bin/bash

To recursively search for a pattern, invoke grep with the -r option (or --recursive). When this option is used, grep searches through all files in the specified directory and its subdirectories, skipping symlinks that are encountered recursively.

To follow all symbolic links , use the -R option (or --dereference-recursive) instead.

Here is an example showing how to search for the string linuxize.com in all files inside the /etc directory:

Terminal
grep -r linuxize.com /etc

The output includes matching lines prefixed by the full path to the file:

output
/etc/hosts:127.0.0.1 node2.linuxize.com
/etc/nginx/sites-available/linuxize.com:    server_name linuxize.com   www.linuxize.com;

If you use the -R option, grep will follow all symbolic links:

Terminal
grep -R linuxize.com /etc

Notice the last line in the output below. It is not printed when grep is invoked with -r because files inside Nginx’s sites-enabled directory are symlinks to configuration files inside sites-available:

output
/etc/hosts:127.0.0.1 node2.linuxize.com
/etc/nginx/sites-available/linuxize.com:    server_name linuxize.com   www.linuxize.com;
/etc/nginx/sites-enabled/linuxize.com:    server_name linuxize.com   www.linuxize.com;

For faster recursive searches in code repositories, ripgrep is often a better default because it respects ignore files and searches recursively without extra flags.

Show Only the Filename

To suppress the default grep output and print only the names of files containing a match, use the -l option (or --files-with-matches).

The following command searches for all files ending with .conf in the current working directory and displays only the file names:

Terminal
grep -l linuxize.com *.conf
output
tmux.conf
haproxy.conf

The -l option is commonly used together with the recursive option -R:

Terminal
grep -Rl linuxize.com /tmp

Show Line Numbers

The -n option (or --line-number) tells grep to prefix each matching line with its line number in the file.

For instance, to display matching lines from /etc/services containing the string 10000 with their line numbers:

Terminal
grep -n 10000 /etc/services

The output shows that the matches are found on lines 10423 and 10424:

output
10423:ndmp            10000/tcp
10424:ndmp            10000/udp

Count Matches

To print only the number of matching lines instead of the lines themselves, use the -c option (or --count).

In the following example, we count the number of accounts that have /usr/bin/zsh as their shell:

Terminal
grep -c '/usr/bin/zsh' /etc/passwd
output
4

The -o option (or --only-matching) tells grep to print only the matched portion of each line, rather than the entire line. This is especially useful when extracting specific patterns with regular expressions.

For example, to extract all words starting with “log” from a file:

Terminal
grep -o 'log[a-z]*' /var/log/syslog | head -5

Context Lines

By default, grep prints only the lines that match. You can use context options to also display lines surrounding each match.

To print a specific number of lines before each match, use the -B option (or --before-context):

Terminal
grep -B 3 "error" /var/log/syslog

To print a specific number of lines after each match, use the -A option (or --after-context):

Terminal
grep -A 3 "error" /var/log/syslog

To print lines both before and after each match, use the -C option (or --context):

Terminal
grep -C 3 "error" /var/log/syslog

When multiple matches are close together, grep separates groups of context lines with --.

Using Grep to Filter Command Output

A command’s output can be filtered with grep through piping, and only lines matching a given pattern will be printed. This is one of the most common uses of grep.

For instance, to find which processes are running as user www-data, you can pipe the output of the ps command to grep:

Terminal
ps -ef | grep www-data
output
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
www-data 31147 12770  0 Oct22 ?        00:05:51 nginx: worker process
www-data 31148 12770  0 Oct22 ?        00:00:00 nginx: cache manager process

Note that grep may also match its own process in the output. A common trick to avoid this is to use a character class in the pattern:

Terminal
ps -ef | grep '[w]ww-data'

By wrapping the first character in brackets, the grep command itself no longer matches the pattern.

Search for Multiple Strings (Patterns)

Two or more search patterns can be joined using the OR operator |.

By default, grep interprets the pattern as a basic regular expression, where | must be escaped with a backslash:

Terminal
grep 'fatal\|error\|critical' /var/log/nginx/error.log

If you use the extended regular expression option -E, the operator does not need to be escaped:

Terminal
grep -E 'fatal|error|critical' /var/log/nginx/error.log

For more complex multi-pattern searches, see Grep Multiple Patterns .

Basic Regular Expressions

GNU Grep has three regular expression feature sets: Basic, Extended, and Perl-compatible.

By default, grep interprets the pattern as a basic regular expression (BRE), where all characters except the meta-characters match themselves.

Below is a list of the most commonly used meta-characters:

  • ^ - Matches the start of a line. In the following example, kangaroo matches only if it occurs at the beginning of a line:

    Terminal
    grep "^kangaroo" file.txt
  • $ - Matches the end of a line. Here, kangaroo matches only if it occurs at the end of a line:

    Terminal
    grep "kangaroo$" file.txt
  • . - Matches any single character. To match anything that begins with kan, then has two characters, and ends with roo:

    Terminal
    grep "kan..roo" file.txt
  • [ ] - Matches any single character enclosed in the brackets. For instance, to find lines that contain accept or accent:

    Terminal
    grep "acce[np]t" file.txt
  • [^ ] - Matches any single character not enclosed in the brackets. The following pattern matches strings like coca or coma, but not cola:

    Terminal
    grep "co[^l]a" file.txt

To escape the special meaning of a meta-character, use the \ (backslash) symbol.

Extended Regular Expressions

To interpret the pattern as an extended regular expression (ERE), use the -E option (or --extended-regexp). Extended regular expressions include all basic meta-characters plus additional ones such as +, ?, |, and ().

Here is an example that matches and extracts all email addresses from a file:

Terminal
grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt

The following example matches and extracts all valid IPv4 addresses from a file:

Terminal
grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt

The -o option prints only the matched portion of each line, not the entire line.

Excluding Files and Directories

When searching recursively, you can exclude specific files or directories using --exclude and --exclude-dir.

To exclude all .log files from a recursive search:

Terminal
grep -r --exclude="*.log" "pattern" /path/to/directory

To exclude multiple file types, repeat the --exclude option:

Terminal
grep -r --exclude="*.log" --exclude="*.tmp" "pattern" /path/to/directory

To exclude a directory from the search:

Terminal
grep -r --exclude-dir="node_modules" "pattern" /path/to/directory

For more details and examples, see Grep Exclude .

Quiet Mode

The -q option (or --quiet) tells grep to run silently without displaying anything on standard output. If a match is found, the command exits with status 0. This is useful in shell scripts where you want to check whether a file contains a string and perform an action based on the result.

Here is an example of using grep in quiet mode as a test command in an if statement :

sh
if grep -q PATTERN filename
then
    echo pattern found
else
    echo pattern not found
fi

Using Shell Variables with Grep

When using grep in shell scripts, you can pass shell variables as the search pattern. Enclose the variable in double quotes to prevent word splitting and globbing:

Terminal
pattern="search term"
grep "$pattern" file.txt

To use a variable as a fixed string (disabling regex interpretation), combine it with the -F option:

Terminal
grep -F "$pattern" file.txt

Limit the Number of Matches

The -m option (or --max-count) tells grep to stop reading a file after a specified number of matching lines. This is useful when working with large files and you only need the first few matches.

For example, to print only the first five lines containing “error” in a log file:

Terminal
grep -m 5 "error" /var/log/syslog

Grep stops reading the file as soon as it finds five matches, which can save a lot of time on large files.

Suppress Error Messages

By default, grep prints error messages when it cannot read a file or when a file does not exist. The -s option (or --no-messages) silences these messages.

This is helpful in shell scripts where you want to ignore “No such file or directory” or “Permission denied” warnings:

Terminal
grep -s "pattern" /etc/*.conf

Any files that cannot be read are skipped silently, and only the actual matches are printed.

Hide Filenames in Output

When grep searches multiple files, it prefixes each matching line with the file name. The -h option (or --no-filename) suppresses these prefixes and prints only the matching lines.

For example, to search for “PermitRootLogin” across all SSH configuration files without showing file names:

Terminal
grep -h "PermitRootLogin" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf

This is useful when piping the output to another command or when the file names would only add noise to the result.

Search Binary Files as Text

Grep treats binary files differently from text files and prints a message like Binary file FILE matches instead of the actual content. The -a option (or --text) forces grep to process binary files as if they were text.

To search for a string in a binary file or a data file that contains non-text bytes:

Terminal
grep -a "version" archive.dat

The matching lines are printed even though the file may contain non-printable characters. Be aware that the output may include control characters that affect your terminal.

Combining Grep with find

When you need more control over which files are searched, combine grep with the find command using -exec. This is helpful when you want to filter by file attributes such as modification time, size, or permissions before searching their contents.

For example, to search for “TODO” in all .py files modified in the last seven days:

Terminal
find . -type f -name "*.py" -mtime -7 -exec grep -l "TODO" {} +

The find command locates the matching files, and grep -l prints the names of files that contain the pattern. Using + instead of \; passes files to grep in batches, which is much faster than invoking grep once for each file.

Quick Reference

For a printable quick reference, see the Grep cheatsheet .

TaskCommand
Search for a stringgrep "pattern" file
Case insensitive searchgrep -i "pattern" file
Whole word matchgrep -w "word" file
Invert matchgrep -v "pattern" file
Recursive searchgrep -r "pattern" /path
Show filenames onlygrep -rl "pattern" /path
Show line numbersgrep -n "pattern" file
Count matchesgrep -c "pattern" file
Print only matching partgrep -o "pattern" file
Lines before matchgrep -B 3 "pattern" file
Lines after matchgrep -A 3 "pattern" file
Lines around matchgrep -C 3 "pattern" file
Multiple patternsgrep -e "pat1" -e "pat2" file
Fixed string (no regex)grep -F "literal.string" file
Exclude filesgrep -r --exclude="*.log" "pattern" /path
Exclude directoriesgrep -r --exclude-dir=".git" "pattern" /path
Recursive with line numbersgrep -rn "pattern" /path
Hide filenamesgrep -h "pattern" file1 file2
Limit matchesgrep -m 5 "pattern" file
Suppress errorsgrep -s "pattern" file
Search binary as textgrep -a "pattern" binary
Find and grepfind . -name "*.py" -exec grep -l "pattern" {} +

FAQ

What does grep do?
The grep command searches text for lines that match a pattern. It reads input from files or standard input, applies a search pattern (either a literal string or a regular expression), and prints every matching line. It is one of the most-used tools for filtering log files, extracting data from command output, and finding code in projects.

What does grep mean?
The name stands for “Global Regular Expression Print”. It comes from the ed text editor command g/re/p, which globally searches for a regular expression and prints matching lines. Grep became a standalone Unix utility in 1973 and has shipped with every major Unix-like system since.

What is the difference between grep and egrep?
The egrep command is equivalent to grep -E. It interprets the pattern as an extended regular expression, which means meta-characters like +, ?, |, and () do not need to be escaped. The egrep command is deprecated in favor of grep -E.

How do I search for a string in all files in a directory?
Use the -r (recursive) option: grep -r "pattern" /path/to/directory. This searches all files in the directory and its subdirectories. Add --include="*.txt" to limit the search to specific file types.

How do I search for multiple words with grep?
Use the -E option with the alternation operator: grep -E "word1|word2|word3" file. Without -E, escape the pipe characters: grep "word1\|word2\|word3" file.

What is the difference between grep, sed, and awk?
Grep is designed for searching and filtering lines that match a pattern. Sed is a stream editor for transforming text with find-and-replace operations. Awk is a full programming language for field-based text processing and data extraction. Use grep to find lines, sed to modify text, and awk to process columnar data.

Conclusion

The grep command is an essential tool for searching text patterns in files and command output. Combined with regular expressions and options like -r, -i, and -E, it handles everything from simple string searches to complex pattern matching.

For more information, see the official Grep manual .

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page