Read in 8 minutes

last updated 

How to Use Grep Command to Search Files in Linux

The grep command which stands for “global regular expression print” is one of the most powerful and commonly used commands in Linux.

Grep searches one or more input files for lines that match a given pattern and writes each matching line to standard output. If no files are specified, grep reads from the standard input which is usually the output of another command.

In this tutorial, we will show you how to use the grep command through practical examples and detailed explanations of the most common GNU grep options.

Grep Command Syntax

Before going into how to use the Grep command, let’s start by reviewing the basic syntax.

The Grep utility expressions take the following form:

grep [OPTIONS] PATTERN [FILE...]

The items in square brackets are optional.

  • OPTIONS - Zero or more options. Grep provides a number of options that control its behavior.
  • PATTERN - Search pattern.
  • FILE - Zero or more input file names.

How to use Grep to 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 example to display the lines from the /etc/passwd file containing the string bash you can use the following command:

grep bash /etc/passwd

The output should look something like this:

root❌0:0:root:/root:/bin/bash
linuxize❌1000:1000:linuxize:/home/linuxize:/bin/bash

If the string includes spaces, you need to enclose it in single or double quotation marks:

grep "Gnome Display Manager" /etc/passwd

Grep Invert Match (Exclude)

To display the lines that do not match a pattern, use the -v ( or --invert-match) option.

For example to display the lines from the /etc/passwd file that do not contain the string nologin you can use the following command:

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

How to use Grep to Search for a String in Command Output

Instead if specifying input files you can pipe the output of another command to grep, and then display only lines matching a given pattern.

For example to find out which processes are running on your system as user www-data you can use the following command:

ps -ef | grep www-data
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
root     18272 17714  0 16:00 pts/0    00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
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

You can also chain multiple pipes in on command. As you can see in the output above there is also a line containing the grep process. If you don’t want that line to be shown pass the output to another grep instance as shown bellow.

ps -ef | grep www-data | grep -v grep
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
root     18272 17714  0 16:00 pts/0    00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
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

To recursively search for a pattern use the, use the -r option (or --recursive). This will search through all files in the specified directory, skipping the symlinks that are encountered recursively. To follow all symbolic links, use the -R option (or --dereference-recursive).

In the following example we are searching for the string linuxize.com in all files inside the /etc directory:

grep -r linuxize.com /etc

The command will print the matching lines prefixed by the full path to the file.

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

If instead -r you use -R option grep will follow all symbolic links:

grep -R linuxize.com /etc

Notice the last line of the output. That line is not printed in the example above because files inside the Nginx’s sites-enabled directory are symlinks to configuration files inside the sites-available directory.

/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;

Grep Show Only Filename

To suppress the default grep output and print only the names of files containing the matched pattern you can use the -l ( or --files-with-matches) option.

For example to search through all files ending with .conf in the current working directory and print only the names of files containing the string linuxize.com type:

grep -l linuxize.com *.conf

The output will look something like this:

tmux.conf
haproxy.conf

The -l option is usually used in combination with the recursive option -R:

grep -Rl linuxize.com /tmp

Grep Case Insensitive

By default the grep command is case sensitive which means that uppercase and lowercase characters are treated as distinct.

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

For example when searching for Zebra without any option the following command will not show any output i.e there are matching lines.

grep Zebra /usr/share/words

But if you perform a case insensitive search using the -i option, it wil match both upper and lower case letters:

grep -i Zebra /usr/share/words

Specifying “Zebra” will match “zebra”, “ZEbrA” or any other combination of upper and lower case letters for that string.

zebra
zebra's
zebras

Grep Exact Match

When searching for gnu grep will also print the lines where gnu is embedded in larger words, such as cygnus or magnum.

grep gnu /usr/share/words
cygnus
gnu
interregnum
lgnu9d
lignum
magnum
magnuson
sphagnum
wingnut

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

Word characters include alphanumeric characters (`a-z`, `A-Z` and `0-9`) and underscores (`_`). All other characters are considered as non-word characters.

If you run the same command as above including the -w option, the grep command will return only those lines where gnu is included as a separate word.

grep -w gnu /usr/share/words
gnu

Grep Show Line Numbers

To show the number of the lines which contains a sting that match a pattern, use the -n ( or --line-number) option. When using this option grep will print the matches to standard output prefixed with the line number it was found on.

For example to display the lines from the /etc/services file containing the string bash prefixed with the matching line number you can use the following command:

grep -n 10000 /etc/services

The output bellow show us that the matches are found on lines 10423 and 10424.

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

Grep Count Matches

To print a count of matching lines to standard output, use the -c ( or --count) option.

In the example bellow we are counting the number of accounts that have /usr/bin/zsh as a shell.

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

Grep Multiple Strings (Patterns)

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

By default Grep interpret the pattern as a basic regular expression where the meta-characters such as | lose their special meaning and their backslashed versions must to be used.

In the example bellow we are searching all occurrences of the words fatal, error and critical in the nginx log error file:

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

If you use the extended regular expression option -E (or --extended-regexp) then the operator | should not be escaped, as shown bellow:

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

Grep Regular Expression

GNU Grep has two regular expression feature sets, Basic and Extended. By default Grep interpret the pattern as a basic regular expression, to switch to extended regular expressions, you need to use the -E option.

When used in basic regular expression mode all other characters except the meta characters, are actually regular expressions that match themselves. Below is a list of most commonly used meta-characters:

  • Use the ^ (caret) symbol to match an expression at the start of a line. In the following example the string ^kangaroo will match only if it occurs at the very beginning of a line.

    grep "^kangaroo" file.txt
  • Use the $ (dollar) symbol to match an expression at the end of a line. In the following example the string kangaroo$ will match only if it occurs at the very end of a line.

    grep "kangaroo$" file.txt
  • Use the . (period) symbol to match any single character. For example, to match anything that begins with kan then has two characters and ends with the string roo, you could use the following pattern:

    grep "kan..roo" file.txt
  • Use [ ] (brackets) match any single character enclosed in the brackets. For example, find the lines that contain accept or “accent, you could use the following pattern:

    grep "acce[np]t" file.txt
  • Use [^ ] (brackets) match any single character enclosed in the brackets. The following pattern will match any combination of strings containing co(any_leter_except_l )a, such as coca, cobalt and so on, but will not match the lines containing cola,

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

To escape the special meaning of the next character use the \ (back slash) symbol.

Grep Extended Regular Expressions

To interpret the pattern as an extended regular expression, use the -E ( or --extended-regexp) option. Extended regular expressions include all of the basic meta-characters, along with additional meta-characters to create more complex and powerful search patterns. Bellow are some examples:

  • Match and extract all email addresses from a given file:

    grep -E -o "\b[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt
  • Match and extract all valid IP addresses from a given file:

    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 is used to print only the matching string.

Grep Print Lines Before a Match

To print a specific number of lines after matching lines, use the -B ( or --before-context) option.

For example to display 5 lines of leading context before matching lines you can use the following command:

grep -A 5 root /etc/passwd

Grep Print Lines After a Match

To print a specific number of lines after matching lines, use the -A ( or --after-context) option.

For example to display 5 lines of trailing context after matching lines you can use the following command:

grep -B 5 root /etc/passwd

Conclusion

In this tutorial, you learned how to use Grep to search for a pattern inside of files. There’s lots more to learn about Grep at Grep User’s Manual page.