21+ Grep Command Examples in Linux – Searching text patterns in files

By | February 18, 2023

Grep Command

Grep command in Linux is primarily used to search files for specific patterns of text, but there is a lot more it can do. The name “grep” is derived from the command used to perform a similar operation "ed" text editor with the operation: g/re/p ((globally search for a regular expression and print matching lines).

Now let's get back to the topic of our article: grep.

Grep Command Examples

Now lets take at some grep command examples that will show you how to use this powerful commandline tool. Grep is used by everyone including, system administrators to search log files, monitor realtime output from other programs, by developers to search source code files etc.

This is a command that you should definitely get your hands on as an expert.

Syntax

The most basic syntax is as follows.

grep [options] PATTERN [FILE...]
grep [options] [-e PATTERN | -f FILE] [FILE...]

1. Simple grep search in a single file

We will start with a simple grep on a text file:

$ grep "ListenAddress" /etc/ssh/sshd_config
#ListenAddress 0.0.0.0
#ListenAddress ::

We see that, in ssh configuration, the ListenAddress is commented out, and we have our first results! We just began the grep journey.

Using with cat command

A very common hack when searching single files, is to combine the use of grep with the cat command like this:

$ cat /var/log/apache2/error.log | grep -in down
3:[Thu Feb 16 10:49:49.963444 2023] [mpm_prefork:notice] [pid 811378] AH00170: caught SIGWINCH, shutting down gracefully
$

First output the contents of a file with cat, then pipe the output to grep. This command is a bit longer, but can often times be easier to remember due to its pipe format. Note the "-n" option which prints the line number where the match was found.

The "-H" option is used to print the file where the match was found. If you use the -H option when piping the cat output it would report "stdin input" like the following:

$ cat /var/log/apache2/access.log.1 | grep auth -inH
(standard input):661:auth
(standard input):661:auth
(standard input):662:auth
(standard input):662:auth
(standard input):663:auth
...

2. Searching multiple files in directory

Checking for strings in multiple files. There will be quite some results in the following query so please scroll to see all of them. We will use the “*” symbol for grep to understand we mean expansion:

$ grep "address" /etc/*
…

grep: /etc/sudoers.d: Is a directory
/etc/sudo_logsrvd.conf:# The hostname or IP address and port to listen on with an optional TLS
/etc/sudo_logsrvd.conf:#   listen_address = hostname(tls)
/etc/sudo_logsrvd.conf:#   listen_address = hostname:port(tls)
/etc/sudo_logsrvd.conf:#   listen_address = IPv4_address(tls)
/etc/sudo_logsrvd.conf:#   listen_address = IPv4_address:port(tls)
/etc/sudo_logsrvd.conf:#   listen_address = [IPv6_address](tls)
…
grep: /etc/sysctl.d: Is a directory
…

If you note carefully, grep first lists the file in which the match was found, and then prints the line with the matching pattern.

I posted just a snippet, but you noticed some sort of warning already:

grep: /etc/sudoers.d: Is a directory

The above indicates that we encountered a directory, and we did not search for it. We'll later see how to “fix” this issue.
Sometimes, we don’t want to go down in the directory tree and just remain at the current folder depth level: like /etc/.

Searching the current directory

Say you are in your home directory and want to search all files. Just use the "period" to specify the current directory as the search target for grep.

$ grep -Ri 'search_term' .

3. Case insensitive

This is perhaps the most powerful option to use with grep. By default, grep is case sensitive, but we can make it case insensitive by using the following switch -i:

With the "-i" option it will match all cases of the search pattern and would potentially show more matches that it would without the "-i" flag.

$ grep -i "password" /etc/ssh/sshd_config
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# PasswordAuthentication. Depending on your PAM configuration,
# the setting of "PermitRootLogin without-password".
# PAM authentication, then enable this but set PasswordAuthentication
PasswordAuthentication yes

Now let’s compare this with the following:

$ grep "password" /etc/ssh/sshd_config
# To disable tunneled clear text passwords, change to no here!
# Change to yes to enable challenge-response passwords (beware issues with
# the setting of "PermitRootLogin without-password".

The difference can be seen easily. Another point to remember is that there is some speed tradeoff between case-sensitive and insensitive searches.

For large volumes of search text/files, a case-insensitive search will be slower since there will be some lowercase/uppercase transforms and potentially other factors. To what degree it is slower and when it deserves an article on its own.

4. Grouping switches

If you just want to print the matched text and not the whole line/sentence where it was found, then use the "-o" option. It was just print the matching text without the rest of the line and each match will be printed on a newline to keep it distinct.

$ grep -io "yes" /etc/ssh/sshd_config \ 
/etc/lvm/lvm.conf
/etc/ssh/sshd_config:yes
/etc/ssh/sshd_config:yes
…
/etc/lvm/lvm.conf:yes

You also see in the example how multiple files can be added to the search list just by providing them as additional parameters to the command. We also used the “\” backslash bash operator, which means that the command continues on the next line. It will be executed when you press enter and there is no “\” on the current line you are writing.

The above example in real life scenario becomes:

$ grep "yes" /etc/ssh/sshd_config /etc/lvm/lvm.conf
/etc/ssh/sshd_config:PermitRootLogin yes
/etc/ssh/sshd_config:#StrictModes yes
/etc/ssh/sshd_config:#PubkeyAuthentication yes
/etc/ssh/sshd_config:# Change to yes if you don't trust ~/.ssh/known_hosts for
/etc/ssh/sshd_config:#IgnoreRhosts yes
/etc/ssh/sshd_config:#PasswordAuthentication yes
/etc/ssh/sshd_config:# Change to yes to enable challenge-response passwords (beware issues with
/etc/ssh/sshd_config:#KerberosOrLocalPasswd yes
/etc/ssh/sshd_config:#KerberosTicketCleanup yes
/etc/ssh/sshd_config:#GSSAPICleanupCredentials yes
/etc/ssh/sshd_config:#GSSAPIStrictAcceptorCheck yes
/etc/ssh/sshd_config:# Set this to 'yes' to enable PAM authentication, account processing,
/etc/ssh/sshd_config:UsePAM yes
/etc/ssh/sshd_config:#AllowAgentForwarding yes
/etc/ssh/sshd_config:#AllowTcpForwarding yes
/etc/ssh/sshd_config:X11Forwarding yes
/etc/ssh/sshd_config:#X11UseLocalhost yes
/etc/ssh/sshd_config:#PermitTTY yes
/etc/ssh/sshd_config:#PrintLastLog yes
/etc/ssh/sshd_config:#TCPKeepAlive yes
/etc/ssh/sshd_config:PasswordAuthentication yes
/etc/lvm/lvm.conf:      # Any 'yes' or 'no' questions not overridden by other arguments are

5. Search in binary files

Grep is designed to work with text, but if needed it can also process binary files with the use of "-a" option. We will also use the “o” switch to print only matching text, useful in not seeing many non-printable characters displayed in results:

root@ubu:~/work# grep -ao "LANGUAGE=" /bin/passwd
LANGUAGE=

Or to see the whole "line" we would use the following. This particular example is not very useful but it's just meant for exercising purposes:

root@ubu:~/work# grep -a "LANGUAGE=" /bin/passwd
can't setuid(0)FORCE_SHADOWyes/var/lib/extrausers/shadowCHFN_AUTHCHSH_AUTHCRACKLIB_DICTPATHENV_HZENVIRON_FILEENV_TZFAILLOG_ENABISSUE_FILELASTLOG_ENABLOGIN_STRINGMAIL_CHECK_ENABMOTD_FILENOLOGINS_FILEOBSCURE_CHECKS_ENABPASS_ALWAYS_WARNPASS_CHANGE_TRIESPASS_MAX_LENPASS_MIN_LENPORTTIME_CHECKS_ENABQUOTAS_ENABSU_WHEEL_ONLYULIMITCHFN_RESTRICTCONSOLE_GROUPSCONSOLECREATE_HOMEDEFAULT_HOMEENCRYPT_METHODENV_PATHENV_SUPATHERASECHARFAKE_SHELLFTMP_FILEHOME_MODEHUSHLOGIN_FILEKILLCHARLASTLOG_UID_MAXLOGIN_RETRIESLOGIN_TIMEOUTLOG_OK_LOGINSLOG_UNKFAIL_ENABMAIL_DIRMAIL_FILEMAX_MEMBERS_PER_GROUPMD5_CRYPT_ENABPASS_MAX_DAYSPASS_MIN_DAYSPASS_WARN_AGESHA_CRYPT_MAX_ROUNDSSHA_CRYPT_MIN_ROUNDSSUB_GID_COUNTSUB_GID_MAXSUB_GID_MINSUB_UID_COUNTSUB_UID_MAXSUB_UID_MINSULOG_FILESU_NAMESYS_GID_MAXSYS_GID_MINSYS_UID_MAXSYS_UID_MINTTYGROUPTTYPERMTTYTYPE_FILEUMASKUSERDEL_CMDUSERGROUPS_ENABSYSLOG_SG_ENABSYSLOG_SU_ENABLANG=LANGUAGE=LC__RLD_=BASH_ENV=HOME=IFS=KRB_CONF=LD_LIBPATH=MAIL=NLSPATH=SHELL=SHLIB_PATH=alldeleteexpirehelpinactivekeep-tokensmindaysquietrepositorystatusunlockwarndaysmaxdaysP
…

6. Recursive grep - Search sub-directories as well

For searching all sub-directories under a given path, we can use the -R switch (can be capital or lowercase, the difference is that capital follows symlinks), which means searching recursively.

The following command will search the current directory recursively for files containing a term.

$ grep -Ri 'config' .

The recursive option will go as deep as possible when looking for sub-directories.

7. Output with Context

Sometimes we need to see the context of a matching text, which is the text preceding or following the match containing line. For this, we have the A,B,C triad of switches, which are namely After, Before and Context switches. They should be followed by a number that prints the number of lines in the context.

Lets take an example. The following search will search all files under /etc/ssh directory recursively, search in binary files also and for each find will display 1 line before and 1 line after: the C context:

$ grep -Ra -C1 "yes" /etc/* | head
/etc/adduser.conf-
/etc/adduser.conf:# If GROUPHOMES is "yes", then the home directories will be created as
/etc/adduser.conf-# /home/groupname/user.
--
/etc/adduser.conf-
/etc/adduser.conf:# If LETTERHOMES is "yes", then the created home directories will have
/etc/adduser.conf-# an extra directory - the first letter of the user name. For example:
--
/etc/adduser.conf-
/etc/adduser.conf:# The USERGROUPS variable can be either "yes" or "no".  If "yes" each

Nice results. We also used the head command, which without any parameters, displays only the first 10 lines of the result. Otherwise, we would have been spammed with tons of text. We’ll soon learn how to gain more control with grep to see only what we are interested in. We started to see the context, but just remember chapter 4: we wanted to see the full line for the match:

$ grep -Ra -C0 "yes" /etc/* | head
/etc/adduser.conf:# If GROUPHOMES is "yes", then the home directories will be created as
--
/etc/adduser.conf:# If LETTERHOMES is "yes", then the created home directories will have
--
/etc/adduser.conf:# The USERGROUPS variable can be either "yes" or "no".  If "yes" each
--
/etc/adduser.conf:USERGROUPS=yes
--
/etc/adduser.conf:# If SETGID_HOME is "yes" home directories for users with their own
--

The command can be also compacted as:

$ grep -RaC0 “yes” /etc/*

Just be careful with command switches order, for example the following won’t work: grep -RC0a!

The "-B" option will print those lines before the matching text line and the "-A" option will print those lines after the matching text line. Its that simple!

8. Colorful Output

Another basic command would be to colorize the output. We will check the kernel ring buffer for keyword info, shorthand for information. Very useful is also to check it for warnings or errors:

$ dmesg | grep -i "info" --color=auto
[    0.011533] ACPI: Using ACPI (MADT) for SMP configuration information

Most modern Linux distributions already display grep output with colors, because they have setup an alias for the grep command with the --color option. You can check this by running the alias command as follows and see how your system is configured.

$ alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

The above output indicates that the switch to colorize the output is always appended to the command.

9. Words with sub-strings

We can also use grep to search for full words containing a specific substring with the "-w" switch. It will select only those lines containing matches that form whole words.

# this will match error everywhere
$ grep -i "error" /var/log/syslog

# this will match the error in: 'SSL error code 1' but not 'net_error'
$ grep -wi "error" /var/log/syslog

10. Match inversion - Exclude some entries

The "-v" switch can be used to exclude specific entries that match a given pattern.

When we grep something in process list, we always see the grep command itself as well. We can exclude it with a second grep command and "-v" option.

$ ps aux | grep bash | grep -v grep
dragos     36272  0.0  0.1   8732  5292 pts/0    Ss   Feb05   0:00 -bash

Lets say you want to display all lines in a file except those that contain a # (which indicates a comment line). Lets scan the /etc/fstab file and see non-comment lines.

$ cat /etc/fstab | grep -v '#'
UUID=19d84ceb-8046-4f8d-a85a-cda49515d92c /               ext4    errors=remount-ro 0       1




UUID=0cc9c458-380f-4600-bc10-afd062c8ae1f none swap sw 0 0

$

11. Counting matches

The "-c" flag will display the count of matches found in each file encountered. This can be useful in some situations like when reading log files.

$ grep -Rc "error" /var/log/*
…
/var/log/dpkg.log.1:23
…
/var/log/syslog:1
/var/log/syslog.1:13
/var/log/syslog.2.gz:0
/var/log/syslog.3.gz:0
/var/log/syslog.4.gz:0
/var/log/ubuntu-advantage.log:0
/var/log/ubuntu-advantage-timer.log:0
/var/log/ubuntu-advantage-timer.log.1:0
/var/log/unattended-upgrades/unattended-upgrades-dpkg.log.1.gz:0
…

12. Stop after N matches

But we might want to stop after a certain number of results, if we only want the first x occurrences.
Stop after n results
Display only first x matches: with m :

$ grep -m1 "password" /etc/ssh/sshd_config
# To disable tunneled clear text passwords, change to no here!

12. Line numbering

The "-n" option will instruct grep to show the line number in the file where the match was found. This can be really powerful if you want to find and then edit something in vi or nano.

$ grep -n "error" /var/log/syslog
1147:Feb 11 10:18:16 ubu root: The installation has errored. Please check.

14. Useful output switches

Sometimes we need to have the output of grep saved to a file. For this, we will be needing the following switches:

-b print the byte offset of the match within the input file
-H print the filename containing a match
-h do not print the filename containing a match
-n print the line number of each match
-T print an initial Tab before matches so that output is aligned

Example: case insensitive search with line numbers:

$ grep -in "^Feb.*enp0.*left.*" /var/log/syslog
1155:Feb 11 10:32:00 ubu kernel: [927982.483352] device enp0s3 left promiscuous mode
…

15. Regular expressions

Now that we know the basics, let's match with regular expressions. This is a powerful feature, and if used properly can spare you a lot of time searching for text in files and logs. With regular expressions you can search for and filter nearly any kind of text pattern provided it can be expressed using regex syntax.

The regex format supported by grep use the following characters with specific meanings:

‘^’ and ‘$’ at the beginning of the pattern anchors the pattern to the start of the line
‘$’ anchors the pattern to the end of the line
‘.’ will match any character
? The preceding item is optional and matched at most once
* The preceding item will be matched zero or more times
+ The preceding item will be matched one or more times
{n} The preceding item is matched exactly n times
{n,} The preceding item is matched n or more times
{,m} The preceding item is matched at most m times
{n,m} The preceding item is matched at least n times, but not more than m times
escaped characters: any special character can be matched as a regular character by escaping it with a ‘\’
\b in a regular expression means "word boundary"; this anchor signifies beginning or end of the word
character range: a set of characters enclosed in a ‘[‘ and ‘]’ square brackets specify a range of characters
-E extended regular expression, almost everything in this group
[:alpha:]	any lower and upper case letter
[:digit:]	            any number.
[:alnum:]	any lower and upper case letter or digit
[:space:]	any whites­pace

The following options control the format of regular expressions that we can feed into grep.

Patterns options:
-F, --fixed-strings   # list of fixed strings
-G, --basic-regexp    # basic regular expression (default)
-E, --extended-regexp # extended regular expression
-P, --perl-regexp     # perl compatible regular expression

The following example will find all IP addresses on all interfaces on the system:

$ ip address | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"
127.0.0.1
192.168.1.25
192.168.1.255
172.18.0.1
172.18.255.255
172.17.0.1
172.17.255.255

And another more complex example: find all IP addresses under /etc/ directory, only one match per file:

$ grep -oERa -m1 "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /etc/*
/etc/alternatives/netcat:0.0.0.0
/etc/alternatives/rlogin:127.0.0.1
………
/etc/systemd/resolved.conf:1.1.1.1
/etc/systemd/resolved.conf:1.0.0.1

16. Grepping multiple patterns

Grep can also search for multiple different patterns in a single command. Just concatenate the patterns with a "\|" character. Note that its a "|" character that is escaped using backslash.

$ grep 'error\|warning' /var/log/syslog
An error occurred with..
…
Warning: The following configuration file is deprecated:..

What is the difference between -e and -E switches ?
-e switch for indicating pattern
-E controls whether you need to escape certain special characters

man grep explains -E in more details:

Basic vs Extended Regular Expressions
In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their 
special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \).

Traditional  egrep  did  not  support  the  {  meta-character, and some egrep 
implementations support \{ instead, so portable scripts should avoid { in grep -E
patterns and should use [{] to match a literal {.

GNU grep -E attempts to support traditional usage by assuming that { is not 
special if it would be the start of an invalid interval specification. 
For example, the command grep -E '{1' searches for the two-character string {1 
instead of reporting a syntax error in the regular expression.  POSIX.2 allows 
this behavior as an extension, but portable scripts should avoid it.

A real life example. We will be searching for error keyword or warning in the syslog files:

$ grep -i 'error\|warning' /var/log/syslog*
/var/log/syslog:Feb 11 10:18:16 ubu root: The installation has errored. Please check.
…
/var/log/syslog.1:Jan 31 14:02:52 ubu networkd-dispatcher[766]: WARNING:Unknown index 4 seen, reloading interface list
/var/log/syslog.1:Jan 31 14:03:19 ubu networkd-dispatcher[766]: WARNING:Unknown index 5 seen, reloading interface list
/var/log/syslog.1:Jan 31 14:03:20 ubu networkd-dispatcher[766]: WARNING:Unknown index 6 seen, reloading interface list

We will see soon, at the end of the article, how this example can be improved!

17. Use search patterns from a file

The "-f" option can be used to specify a file containing a list of patterns one in each line. This allows us to search for lots of patterns in one go, without having to specify a long list on the command line itself.

$ grep -f pattern_file content_file | head
xyz
darboard
012
gang
tt

Here are the contents of the files.

$ cat pattern_file
[abc]
[def]
[0-9]
[a-z]

$ cat content_file
xyz
darboard
012
gang
tt

18. Literal matching

Another more advanced usage of grep is using the "-F" switch, which is different from "-f". The "-F" option will determine patterns to match literally - no regex interpretation will be done on the pattern(s):

$ grep -F $'conf' <<< $'\n/etc/ssh/\nconf'
conf

Here we used the $ following by a quoted string. More information can be found on this page.

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.

Basically, we wanted the escape character \n to be replaced by its ANSI code and then we instructed grep to search in that string for the occurrences of conf(conf usually is a prefix of configuration files). Also of importance is the fact that ‘-F’ involves not using regex which speeds up the search for large files.

19. Piping

We sometimes want to parse the output of another command with grep, and this is called piping, please see the following example:

$ sudo dmesg | grep -i error
[    4.962448] [drm:vmw_host_printf [vmwgfx]] *ERROR* Failed to send host log message.

Where the output of the kernel ring buffer was piped - sent - to grep as input, then we searched for error messages and we found one. Sudo was used because a regular user cannot access the kernel ring buffer without it.

And the promised example from chapter 9. We finally made it to more cadvanced examples, something Linux sysadmins need frequently like seeing enabled parameters in configuration files:

$ grep -v "#" /etc/ssh/sshd_config | grep -E "\s"
Include /etc/ssh/sshd_config.d/*.conf
PermitRootLogin yes
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp  /usr/lib/openssh/sftp-server
PasswordAuthentication yes

Please pay attention: the following example will not produce the same results as before:

$ grep -v "#" -E “\s” /etc/ssh/sshd_config

It will produce results but not the same one because here the E switch will enable extended grep features and “#” will be treated differently, not as literal “#”.

20. Suppressing error messages

Grep sometimes(if used incorrectly mostly) yields errors and in such scenarios it's useful to make it quiet with:
-s or –no-messages switches. In the example below we will get a lot of permission denied errors that we can suppres with -s:

$ grep -ER "=*yes" /etc/*
/etc/systemd/journald.conf:#ReadKMsg=yes
/etc/systemd/system.conf:#LogColor=yes
/etc/systemd/system.conf:#DumpCore=yes
/etc/systemd/system.conf:#ShowStatus=yes
/etc/systemd/system.conf:#DefaultMemoryAccounting=yes
/etc/ufw/ufw.conf:# Set to yes to start on boot. If setting this remotely, be sure to add a rule
/etc/usb_modeswitch.conf:# To enable an option, set it to "1", "yes" or "true" (case doesn't matter)
…

Suppressed errors results:

$ grep -sRE "=*yes" /etc/* | tail
/etc/systemd/journald.conf:#ReadKMsg=yes
/etc/systemd/system.conf:#LogColor=yes
/etc/systemd/system.conf:#DumpCore=yes
/etc/systemd/system.conf:#ShowStatus=yes
/etc/systemd/system.conf:#DefaultMemoryAccounting=yes
/etc/systemd/system.conf:#DefaultTasksAccounting=yes
/etc/ufw/ufw.conf:# Set to yes to start on boot. If setting this remotely, be sure to add a rule
/etc/usb_modeswitch.conf:# To enable an option, set it to "1", "yes" or "true" (case doesn't matter)
…

Above we search recursively in the /etc/ directory for files of which lines have = yes in their configuration.

Let’s make this more useful. Let’s search for yes configuration lines followed by space any number of times and suppres errors at the same time, and only show the end of the results (for not spamming the terminal, in a real case scenario you would want it without tail or sent to a file):

$ grep -sRE "=[[:space:]]+yes" /etc/* | tail
/etc/samba/smb.conf:   pam password change = yes
/etc/samba/smb.conf:   usershare allow guests = yes
/etc/samba/smb.conf:;   read only = yes
/etc/samba/smb.conf:;   guest ok = yes
/etc/samba/smb.conf:;   read only = yes
/etc/skel/.bashrc:if [ "$color_prompt" = yes ]; then
/etc/sos/sos.conf:#verify = yes
/etc/sos/sos.conf:#batch = yes
/etc/ssl/openssl.cnf:ordering           = yes   # Is ordering defined for timestamps?
/etc/ssl/openssl.cnf:tsa_name           = yes   # Must the TSA name be included in the reply?

yes and no:

$ grep -sRE "=[[:space:]]+yes|=[[:space:]]+no" /etc/* | tail
/etc/ssl/openssl.cnf:preserve   = no                    # keep passed DN ordering
/etc/ssl/openssl.cnf:# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
/etc/ssl/openssl.cnf:keyUsage = nonRepudiation, digitalSignature, keyEncipherment
/etc/ssl/openssl.cnf:# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
/etc/ssl/openssl.cnf:ordering           = yes   # Is ordering defined for timestamps?
/etc/ssl/openssl.cnf:tsa_name           = yes   # Must the TSA name be included in the reply?
/etc/ssl/openssl.cnf:ess_cert_id_chain  = no    # Must the ESS cert id chain be included?
/etc/sudo_logsrvd.conf:#accept_priority = notice

21. Other useful switches

Another useful switches that are worth looking into are:
-x, --line-regexp force PATTERN to match only whole lines
-z, --null-data a data line ends in 0 byte, not newline

A more complete command switch for you to have is:
grep -HhrilLnqvsoweFEABCz PATTERN FILE

Think of it more like a cheat sheet or a mnemonic.

Congratulations, you reached almost the end of the article, lets see some more real life examples, using everything we’ve learned:

Seeing all enabled parameters in a configuration file that is using “#” as a line comment:

$ grep -v "#" /etc/ssh/sshd_config | grep -E "\s"
Include /etc/ssh/sshd_config.d/*.conf
PermitRootLogin yes
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp  /usr/lib/openssh/sftp-server
PasswordAuthentication yes

Find errors in all files changed in the last 24 hours under /var/log directory recursively, and print the matching line. Also scroll the text with more command - this command allows you to scroll at own pace in results with keyboard:

find /var/log/ -name '*' -exec grep -H "error" {} \;

Searching for a number in square brackets:
Suppose we want to search for “[50]”

$ echo "[50]" | grep '\[[^]]*50[^]]*]'
[50]
What we just did:
\[: matches a [
[^]]*: matches 0 or of any characters that are not ]
50: maatches text 50
[^]]*: Match 0 or of any characters that are not ]
]: Match a ]

Find lines not containing pattern. A variation of a previous example:

$ grep -vE "^#" /etc/ssh/sshd_config | grep "[[:space:]]"
Include /etc/ssh/sshd_config.d/*.conf
PermitRootLogin yes
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp  /usr/lib/openssh/sftp-server
PasswordAuthentication yes

Set how many lines to show before (-B) and after (-A) pattern:

root@ubu:~/work# grep -B 3 -A 2 ".*err" /var/log/syslog
Feb 11 09:17:01 ubu CRON[67703]: (root) CMD (   cd / &amp;&amp; run-parts --report /etc/cron.hourly)
Feb 11 10:17:01 ubu CRON[67993]: (root) CMD (   cd / &amp;&amp; run-parts --report /etc/cron.hourly)
Feb 11 10:17:20 ubu root: Error 1
Feb 11 10:18:16 ubu root: The installation has errored. Please check.
Feb 11 10:31:59 ubu kernel: [927981.373038] Bluetooth: Core ver 2.22
Feb 11 10:31:59 ubu kernel: [927981.373186] NET: Registered PF_BLUETOOTH protocol family

Find all files that match in

$ grep -rnw /var/log/ -e ".*\.h$" | tail
…
/usr/share/man/man7/openssl-core.h.7ssl.gz
/usr/share/man/man7/openssl-core_dispatch.h.7ssl.gz
/var/log/aide/aide.log:101232:File: /usr/share/man/man7/openssl-core_names.h.7ssl.gz

Variation of excluding grep from the output of ps: surround first letter of desired search result with “[]”:

# ps aux | grep '[b]ash'
dragos     36272  0.0  0.1   8996  4644 pts/0    Ss   Feb05   0:00 -bash
root       61324  0.0  0.1   9052  5496 pts/1    S    Feb09   0:00 -bash
root       64699  0.0  0.1   9052  5676 pts/4    Ss   Feb10   0:00 -bash
root       67421  0.0  0.1   9292  5952 pts/2    Ss   07:19   0:02 -bash
[term]

Colorization of search pattern only, in results, and display all other results: nginx will appear colorized:

[term]
$ ps aux | grep -E --color 'nginx|$'
…
root       70233  0.0  0.0  10068  1568 pts/2    R+   17:19   0:00 ps aux
root       70234  0.0  0.0   6608  2288 pts/2    S+   17:19   0:00 grep --color=auto -E --color nginx|$

22. "Find" files with grep

The grep command can be used to search for files and this makes it a really powerful tool. Usually you would use the find command to search for files from the command line on linux. However even grep can come in handy for the same task if used correctly.

The basic idea is to use the output of the ls command and filter it using grep. Here is a quick example

$ ls -lR /etc/ | grep conf | head -n5
-rw-r--r-- 1 root          root           3028 Aug  9  2022 adduser.conf
...

We recursively list all files with ls and then we feed the output to grep, and search for conf in their names. We limit the output to only 5 entries with the head command.

23. Searching archives

The grep command can search for patterns in regular files. But what if you want to search files that compressed ? For example log files on linux system are often split and compressed. Apache access and error log files are stored like this for example.

The "zgrep" command can be used to search compressed files in nearly the same way as grep would search a regular file.

In order to search in archives, we will use the zgrep equivalent exactly as we used grep. This is another very useful tip in production environments where logs are many times archived.

$ zgrep -i 'get' /var/log/apache2/*

Here is another example. Grepping for errors and warnings in syslog archived files and non archived files:

$ zgrep -i 'error\|warning' /var/log/syslog*
...

Conclusion

1. Variations of grep

There are many variations of the grep command like egrep, zgrep etc. Each variation supports different features beyond the base grep command. Use the apropos command to get a list of all grep variants.

$ apropos grep
bzegrep (1)          - search possibly bzip2 compressed files for a regular expression
bzfgrep (1)          - search possibly bzip2 compressed files for a regular expression
bzgrep (1)           - search possibly bzip2 compressed files for a regular expression
egrep (1)            - print lines that match patterns
fgrep (1)            - print lines that match patterns
git-bugreport (1)    - Collect information for user to file a bug report
git-grep (1)         - Print lines matching a pattern
grep (1)             - print lines that match patterns
lzegrep (1)          - search compressed files for a regular expression
lzfgrep (1)          - search compressed files for a regular expression
lzgrep (1)           - search compressed files for a regular expression
pgrep (1)            - look up, signal, or wait for processes based on name and other attributes
ptargrep (1)         - Apply pattern matching to the contents of files in a tar archive
rgrep (1)            - print lines that match patterns
xzegrep (1)          - search compressed files for a regular expression
xzfgrep (1)          - search compressed files for a regular expression
xzgrep (1)           - search compressed files for a regular expression
zegrep (1)           - search possibly compressed files for a regular expression
zfgrep (1)           - search possibly compressed files for a regular expression
zgrep (1)            - search possibly compressed files for a regular expression
zstdgrep (1)         - print lines matching a pattern in zstandard-compressed files

Out of all the commands above the most popular one is zgrep, and its position is well worth it since it spares us from unfolding archives and deleting afterwards.

The version of grep available in Ubuntu 22.04 LTS, a popular Linux distribution is 3.7:

$ apt info grep
Package: grep
Version: 3.7-1build1
….

If you want to have the latest version, you can compile it from sources from this url, at the time of this writing 3.8: https://git.savannah.gnu.org/cgit/grep.git/snapshot/grep-3.8.tar.gz

2. Tips

Tips:
grep returns 0 if it matches your query, and non-zero if it does not!

Now you have all the basics and even advanced usages of grep to search files and logs on your system.

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

Leave a Reply

Your email address will not be published. Required fields are marked *