Updated: 11 October 2026 · Applies to: GNU grep 3.11 on Debian 13, Ubuntu 24.04 and AlmaLinux 10.2; ripgrep 14.1.1 on Debian 13

To find every file that contains a word or a string in Linux, run grep -rn "text" /path/to/folder. -r searches all files in the folder and its subfolders, and -n shows the line number of each match. Use grep -rl to print only the file names, and add -i to ignore upper and lower case:

grep -rn "db_host" /home/user/public_html
grep -rli "db_password" /home/user/public_html

grep searches the contents of files. To find a file by its name, use find instead: see find a file in Linux by name. Everything below was tested on a lab folder (a small PHP site in /srv/site) with GNU grep 3.11 on Debian 13, Ubuntu 24.04 and AlmaLinux 10.

Search for text in one file

Give grep the text and the file. It prints every matching line, and -n adds the line number:

$ grep -n "ServerName" /srv/conf/site.conf
3:    ServerName example.com

With several files (grep -n "ServerName" /srv/conf/*.conf) grep puts the file name in front of each line. To search a long file by hand, open it with less, type / and the text, then press Enter; n jumps to the next match and N back to the previous one.

Find all files containing the text, step by step

  1. Choose the folder. Name it in the command, or go into it first: without a folder, grep -r searches the current folder.
  2. Run the recursive search. Each result reads file:line:text:
    $ grep -rn "db_host" /srv/site
    /srv/site/node_modules/pkg/config.ini:1:db_host=127.0.0.1
    grep: /srv/site/blob.bin: binary file matches
    /srv/site/inc/db.php:3:$db_host = "localhost";
  3. List only the file names if that is all you need:
    $ grep -rl "db_host" /srv/site
    /srv/site/node_modules/pkg/config.ini
    /srv/site/blob.bin
    /srv/site/inc/db.php
  4. Narrow it down. Skip binary files with -I, folders you do not care about with --exclude-dir, and search only some file types with --include:
    $ grep -rnI --exclude-dir=node_modules --include="*.php" "db_host" /srv/site
    /srv/site/inc/db.php:3:$db_host = "localhost";

Options you will use most

  • -i: ignore case. grep -rni "db_host" also found DB_HOST in wp-config.php.
  • -w: whole words only. Careful: grep -rlw "db" did not find db_host, because the underscore counts as part of a word.
  • -l and -L: list the files that do, or do not, contain the text. grep -rL "db_host" --include="*.php" /srv/site returned only wp-config.php.
  • -c: count the matching lines in each file.
  • --include="*.php", --exclude="*.min.js" and --exclude-dir=node_modules: choose which files and folders to search. Repeat an option for more patterns.
  • -I: skip binary files. Without it, grep reports a match in a binary file as grep: FILE: binary file matches.
  • -A 2, -B 2 and -C 2: also show 2 lines after, before or around each match.
  • -o: print only the matched part, which is handy for counting: grep -rho "DB_[A-Z]*" /srv/site | sort | uniq -c.
  • -R: like -r, but also follows symbolic links. In our test grep -r skipped a linked config folder that grep -R searched.

Special characters, several words and text starting with a dash

grep -rF "price[5]" /srv/site/logs              # -F: the literal text, no regular expression
grep -rniE "error|warning" /srv/site/logs      # -E: either word, any case
grep -rn -e "DB_NAME" -e "table_prefix" /srv/site
grep -rn -e "-v" /srv/conf                      # text that starts with a dash
  • Without -F, grep -r "price[5]" found nothing: square brackets are a regular expression, so grep looked for price5.
  • grep "-v" help.txt does not search for -v. grep reads it as its "invert match" option, takes help.txt as the text to find and then waits for input from the keyboard (press Ctrl+C). Use -e "-v" or -- "-v".

Files that contain two words (AND)

grep has no AND across a whole file, so chain two searches. -Z and xargs -0 keep file names with spaces intact:

$ grep -rlZ "localhost" /srv/site | xargs -0 grep -l "DB_NAME"
/srv/site/wp-config.php

Let find choose the files, and search compressed logs

When the condition is not about the content, for example only files changed in the last day, let find pick the files and grep search them:

find /srv/site -name "*.php" -mtime -1 -exec grep -l "localhost" {} +

Rotated logs that end in .gz are compressed, so plain grep cannot read them. zgrep takes the same options:

$ zgrep -i "timeout" /srv/site/logs/app.log.1.gz
ERROR: timeout

Permission denied and exit codes

As a normal user, a search through /etc prints lines such as grep: /etc/shadow: Permission denied. Add -s (or 2>/dev/null) to hide them, or run the search with sudo if you need those files too. In scripts, use grep -q and check the exit code:

  • 0: the text was found.
  • 1: the text was not found.
  • 2: an error, such as a missing or unreadable file. -s hides the message but not the error: in our test grep -rls "root" /etc/shadow /etc/passwd listed /etc/passwd and still exited with 2.

ripgrep for code folders

rg (package ripgrep on Debian and Ubuntu) works like grep -rn but skips hidden files and everything listed in .gitignore by default. In our test rg -n "db_host" . found only inc/db.php, while rg -n -uu "db_host" . also searched a hidden file and the ignored node_modules folder. Always give rg a folder in scripts: without one, and with input piped in, it searches that input instead of the disk. Similar tool: The Silver Searcher (ag).

Tips

  • Searching the whole system (grep -r "text" /) is slow and floods the screen with errors. Search where the file probably is: /etc for configuration, /var/log for logs, your site folder for code.
  • On cPanel hosting, run these commands in Terminal in cPanel or over SSH, inside your home folder.
  • To change the text once you have found it, see find and replace a word in a whole folder.

More grep: advanced grep with character classes and grep, egrep and fgrep.

Ucartz services for this topic

Was this answer helpful? 0 Users Found This Useful (0 Votes)