Skip to main content
Blog|
Learning center

Find and Grep: Searching Files and Text on Linux Servers

|
Feb 28, 2026|8 min read
LEARNING CENTERFind and Grep: Searching Filesand Text on Linux ServersHOSTNEYhostney.comOctober 10, 2023

Two commands handle most of the searching you’ll ever do on a Linux server: find locates files, grep searches inside them. Between the two, you can track down just about anything.

These aren’t obscure tools. They’re the kind of commands you’ll run multiple times a day once you’re comfortable with them. Need to find every .log file modified in the last 24 hours? find . Need to figure out which config file contains a specific database hostname? grep . Need to do both at once? Pipe them together.

This guide covers both commands in depth, from basic usage through advanced patterns, plus a few alternative tools worth knowing about.

Finding files with find#

The find command walks a directory tree and returns files that match your criteria. Unlike ls , which only shows the current directory, find goes as deep as you want, checking every subdirectory along the way.

Basic file search

The simplest use: find a file by name.

find /var/www -name "wp-config.php"

This searches /var/www and everything below it for a file named wp-config.php . The path at the beginning tells find where to start. Use . for the current directory, / for the entire filesystem, or any specific path.

Wildcard patterns

When you don’t know the exact filename, wildcards help. The asterisk matches any sequence of characters:

find /var/log -name "*.log"

This returns every file ending in .log under /var/log . Wrap the pattern in quotes so the shell doesn’t expand the wildcard before find gets to it. This is a common gotcha; without quotes, the shell tries to match *.log against files in the current directory instead of passing the pattern to find .

You can also match partial names:

find . -name "backup*"

This catches backup.sql , backup-2026-02-15.tar.gz , backup_notes.txt , and anything else starting with “backup.”

Filtering by type

By default, find returns both files and directories. Narrow it down with -type :

# Only regular files
find /etc -type f -name "*.conf"

# Only directories
find /home -type d -name "public_html"

# Only symbolic links
find /usr/local -type l

Filtering by modification time

This is where find becomes genuinely useful for server administration. When something breaks at 3 AM and you need to figure out what changed, modification time filters are the answer.

# Files modified in the last 24 hours
find /etc -type f -mtime -1

# Files modified more than 30 days ago
find /var/log -type f -mtime +30

# Files modified in the last 2 hours (use -mmin for minutes)
find /var/www -type f -mmin -120

The number after -mtime is in days. A minus sign means “less than,” a plus sign means “more than,” and no sign means “exactly.” The -mmin variant works the same way but counts minutes instead of days.

Filtering by size

Track down files eating your disk space:

# Files larger than 100MB
find / -type f -size +100M

# Files larger than 1GB
find / -type f -size +1G

# Files smaller than 1KB (possibly empty or stub files)
find /var/www -type f -size -1k

Filtering by owner

Useful when cleaning up after a user or tracking down permission issues:

# Files owned by a specific user
find /home -type f -user john

# Files owned by a specific group
find /var/www -type f -group www-data

Combining criteria

find lets you chain multiple conditions. By default, all conditions must be true (AND logic):

# PHP files modified in the last 3 days, larger than 10KB
find /var/www -type f -name "*.php" -mtime -3 -size +10k

For OR logic, use -o with parentheses (escaped for the shell):

# Files ending in .log OR .tmp
find /var -type f \( -name "*.log" -o -name "*.tmp" \)

Acting on results

find can do more than list files. The -exec flag runs a command on each result:

# Delete all .tmp files older than 7 days
find /tmp -type f -name "*.tmp" -mtime +7 -exec rm {} \;

# Change permissions on all PHP files
find /var/www -type f -name "*.php" -exec chmod 644 {} \;

The {} is a placeholder for each file found, and \; marks the end of the command. If you’re running a command on many files, + is more efficient than \; because it batches the files:

find /var/www -type f -name "*.php" -exec chmod 644 {} +

Searching text with grep#

While find locates files by name, type, or metadata, grep searches inside files for text patterns. It reads through file contents line by line and prints every line that matches your pattern.

Basic text search

Search a single file for a string:

grep "database" /etc/myapp/config.php

This prints every line in config.php that contains the word “database.”

Recursive search

When you don’t know which file contains the text, search an entire directory tree:

grep -r "database_host" /etc/

The -r flag tells grep to recurse through all files under /etc/ . This is probably the most common way to use grep on a server. Something is referencing a hostname or IP address and you need to find where.

Show only filenames

Sometimes you just want to know which files contain the match, not the matching lines themselves:

grep -rl "old-domain.com" /var/www/

The -l flag suppresses the line output and prints only filenames. Useful when you’re planning a find-and-replace across a project and need to see the scope first.

Case-insensitive search

By default, grep is case-sensitive. “Error” and “error” are different strings. The -i flag makes it ignore case:

grep -ri "error" /var/log/nginx/

This catches “Error,” “ERROR,” “error,” and any other capitalization variant.

Show line numbers

When you need to know where in the file the match occurs:

grep -n "timeout" /etc/nginx/nginx.conf

The -n flag prepends each matching line with its line number. Saves you from opening the file and scrolling to find the match.

Count matches

If you just need to know how many times a pattern appears:

grep -c "404" /var/log/nginx/access.log

This outputs a single number: the count of matching lines.

Show context around matches

A matching line by itself isn’t always enough to understand what’s going on. Context flags show surrounding lines:

# 3 lines after each match
grep -A 3 "error" /var/log/app.log

# 3 lines before each match
grep -B 3 "error" /var/log/app.log

# 3 lines before and after
grep -C 3 "error" /var/log/app.log

Regular expressions

Grep supports regular expressions, which let you match patterns rather than literal strings.

# Lines starting with "error"
grep "^error" logfile.log

# Lines ending with a number
grep "[0-9]$" data.txt

# Lines containing an IP address pattern
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" access.log

The -E flag enables extended regex, which supports operators like | (OR), + (one or more), and {} (quantifiers) without needing to escape them.

# Lines containing "error" OR "warning"
grep -E "error|warning" /var/log/syslog

Inverting matches

The -v flag returns lines that don’t match the pattern. Useful for filtering out noise:

# Show all log lines except those containing "DEBUG"
grep -v "DEBUG" /var/log/app.log

# Show non-empty lines
grep -v "^$" config.file

Piping into grep

One of grep’s most practical uses is filtering the output of other commands:

# Find a specific process
ps aux | grep nginx

# Find a specific package
rpm -qa | grep php

# Filter file listings
ls -la /etc/ | grep "ssl"

This works because grep reads from standard input when you pipe into it. Any command’s output can be filtered this way.

Combining find and grep#

Individually, find and grep cover different ground. Together, they handle searches that neither can do alone: finding files that match certain criteria and then searching inside those files for specific text.

Search within found files

Find all PHP files under /var/www and search each one for database credentials:

find /var/www -type f -name "*.php" -exec grep -l "db_password" {} +

This returns only the filenames containing “db_password.” Without the combination, you’d either grep through every file (including images, binaries, and other irrelevant files) or manually check each PHP file individually.

Time-based content searches

Find log files modified today and search them for errors:

find /var/log -type f -name "*.log" -mtime -1 -exec grep -H "CRITICAL" {} +

The -H flag ensures grep prints the filename alongside each match, so you know which log file the error came from.

Complex pattern matching

Find config files and search for lines referencing either a staging or production database:

find /etc -type f -name "*.conf" -exec grep -HnE "(staging|production)_db" {} +

This combines find’s file-location ability with grep’s regex support and line numbering. The output tells you exactly which file, which line number, and which database reference was found.

An alternative: grep -r with –include

For simpler cases, you can skip find entirely and use grep’s built-in file filtering:

grep -rn --include="*.php" "db_password" /var/www/

The --include flag limits the recursive search to files matching the pattern. This is often faster to type than a full find / grep combination, though find gives you more filtering options (size, time, owner) that grep can’t match.

Other useful search commands#

locate: fast filename searches

The locate command searches a pre-built database of filenames, making it much faster than find for simple name lookups:

locate nginx.conf

The database is updated periodically by a cron job running updatedb . This means recently created files might not appear in results until the database is refreshed. Run sudo updatedb manually if you need current results.

whereis: finding binaries and documentation

whereis locates the binary, source code, and manual page for a command:

whereis nginx
# nginx: /usr/sbin/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz

Useful when you need to know where a program is installed, especially when multiple versions might exist on the system.

which: finding the active binary

which tells you exactly which executable runs when you type a command:

which python3
# /usr/bin/python3

This resolves your PATH and shows the first match. Handy when you have multiple versions installed and need to confirm which one is being used.

Quick reference#

TaskCommand
Find file by name find /path -name "filename"
Find files by extension find /path -type f -name "*.ext"
Find recently modified files find /path -type f -mtime -1
Find large files find /path -type f -size +100M
Search file contents grep "pattern" filename
Recursive text search grep -r "pattern" /path/
Case-insensitive search grep -ri "pattern" /path/
Show filenames only grep -rl "pattern" /path/
Find files then search contents find /path -name "*.ext" -exec grep -l "pattern" {} +
Filter command output command | grep "pattern"

Check out the GNU Coreutils documentation and the grep manual for the complete reference.

Manage your servers with confidence. Try Hostney web hosting free for 14 days.