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
- Choose the folder. Name it in the command, or go into it first: without a folder,
grep -rsearches the current folder. - 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";
- 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
- 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 foundDB_HOSTin wp-config.php.-w: whole words only. Careful:grep -rlw "db"did not finddb_host, because the underscore counts as part of a word.-land-L: list the files that do, or do not, contain the text.grep -rL "db_host" --include="*.php" /srv/sitereturned 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 asgrep: FILE: binary file matches.-A 2,-B 2and-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 testgrep -rskipped a linked config folder thatgrep -Rsearched.
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 forprice5. grep "-v" help.txtdoes not search for-v. grep reads it as its "invert match" option, takeshelp.txtas 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.-shides the message but not the error: in our testgrep -rls "root" /etc/shadow /etc/passwdlisted/etc/passwdand 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:/etcfor configuration,/var/logfor 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
- KVM VPS hosting: NVMe SSD and full root access, with Free Basic Managed Support.
- Unmanaged dedicated servers: full root access and free IPMI KVM, with Free Basic Managed Support.
- Linux server management: hardening, patching, monitoring and automation for Ubuntu, Debian, RHEL and AlmaLinux.
