Grep to search for text in files on the command line

Grep to search for text in files on the command line

Have you ever wanted to search for text in different files while you are inside the terminal? We all do, and luckily, grep is here for the rescue.

Screenshot 2020-05-23 at 13.42.05.png

Grep is a simple but powerful tool that comes with every linux distribution and macos out of the box. Personally, I use it in my day-to-day work, as its quiet effective and fast, much faster and simpler than searching inside of an IDE. Its not just effective because its easy to use, but also because it could be combined with other commands that could help you further in finding what are you looking for, we will see that in the examples down below.

How does it work?

Grep searches one or more input files for lines containing a match to a specified pattern. By default, Grep outputs the matching lines. Dead simple, just like that, you pass the pattern/word you want to search for, the list of files as input, and tada! you get results.

In the very simplest form in using grep a command would look like that:

grep 'test' somefile.py

This short command searches for the word test in the file somefile.py. pretty neat, right? not yet, in my case usually I want to search for text in all files in a certain directory, let's jump to more examples.

Usage examples:

Search in a directory (Recursively)

We can pass options to the grep command to gain different behavior, and one of these options is the -R recursive search, where you can pass a directory and grep will recursively search all the files in that directory, and all sub-directories too!

grep -R 'test' somedirectory

The result would look like this:

commit-msg.sample:test "" = "$(grep '^Signed-off-by: ' "$1" |
pre-rebase.sample:if test "$#" = 2
pre-rebase.sample:if test -z "$not_in_master"
pre-rebase.sample:if test "$only_next_1" = "$only_next_2"
pre-rebase.sample:    if test -z "$not_in_topic"
pre-rebase.sample: * Whenever you need to test or publish your changes to topic
pre-commit.sample:    test $(git diff --cached --name-only --diff-filter=A -z $against |
applypatch-msg.sample:test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
pre-receive.sample:if test -n "$GIT_PUSH_OPTION_COUNT"
pre-receive.sample:    while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
prepare-commit-msg.sample:# if test -z "$COMMIT_SOURCE"
pre-applypatch.sample:test -x "$precommit" && exec "$precommit" ${1+"$@"}

quite nice, but I still want to see line numbers, as this is not 100% helpful.

Show linenumbers

Here comes another useful option that tells grep to show the linenumbers where it found the text we search for.

grep -Rn 'test' somedirectory

Have you noticed how we combined the options? This will tell grep to search recursively and show the line numbers!

commit-msg.sample:20:test "" = "$(grep '^Signed-off-by: ' "$1" |
pre-rebase.sample:20:if test "$#" = 2
pre-rebase.sample:47:if test -z "$not_in_master"
pre-rebase.sample:56:if test "$only_next_1" = "$only_next_2"
pre-rebase.sample:59:    if test -z "$not_in_topic"
pre-rebase.sample:107: * Whenever you need to test or publish your changes to topic
pre-commit.sample:31:    test $(git diff --cached --name-only --diff-filter=A -z $against |
applypatch-msg.sample:14:test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
pre-receive.sample:9:if test -n "$GIT_PUSH_OPTION_COUNT"
pre-receive.sample:12:    while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
prepare-commit-msg.sample:39:# if test -z "$COMMIT_SOURCE"
pre-applypatch.sample:13:test -x "$precommit" && exec "$precommit" ${1+"$@"}

I loved it

Insensitive case search

Sometimes we want to search for text regardless of its case, for example we would like to get results that could contain something like "TEST", "Test", "TeSt" or just "test". For that we use the -i flag to tell grep to find any match, and ofcourse we can combine that with other options.

grep -iRn 'test' somedirectory

and that's usually how my command looks like most of the time.

Find text in selected files only

The following command is absolutely one of my best tricks that saves me a lot of time, without it I would just be lost. The idea is to pass the output from the find command to grep as input.

Let's say we would like to search for the word "test" recursively in a directory that contains lots of different files, buy we would like to search only in files with certain names, or files that end in a certain extention, like .py python files, here is how the command would look like:

find . -name '*.py' -exec grep -iRn 'test' {} +

Fantastically and amazingly you get only results from files that ends in .py and contains the word test anywhere.

wow