Skip to content

Searching inside files on Linux#

These are two different questions, answered by two different commands: "where is a file with this name" is not the same as "which file contains this text." find answers the first, grep -r the second - and most of the time you need both together.

Search by filename: find#

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

Finds every file under /var/www, including subdirectories, whose name ends in .log. For case-insensitive matching, use -iname:

find /var/www -iname "*.PHP"

The find filters you will actually use#

find /home -type f -name "*.conf"        # files only, not directories
find /home -type d -name "cache"          # only directories named "cache"
find /var/log -type f -mtime -7           # files modified in the last 7 days
find /var/log -type f -size +100M         # files larger than 100MB
find / -user www-data 2>/dev/null         # files owned by www-data

-mtime -7 means "newer than 7 days", -mtime +7 means "older than 7 days" - the plus/minus sign is easy to read backwards, so double-check it.

Doing something with what find finds: -exec

find /var/log -name "*.log" -mtime +30 -exec rm {} \;

Deletes every .log file older than 30 days. {} is replaced with each matched file, \; marks the end of the command. Before an irreversible operation like -exec rm, run with -print first to see what you are about to delete.

Search by file content: grep -r#

grep -r "ERROR" /var/log/nginx/

Scans every file under a directory, including subdirectories, and prints lines that contain "ERROR". Useful additions:

grep -rn "ERROR" /var/log/nginx/          # with line numbers
grep -rl "ERROR" /var/log/nginx/          # just the matching filenames, not the lines
grep -ri "error" /var/log/nginx/          # case-insensitive
grep -r --include="*.log" "ERROR" /var/log/   # only search .log files
grep -r --exclude-dir=node_modules "TODO" .   # skip this directory entirely

-l (lowercase L) is particularly handy: it answers "which files contain this text" as a list, so you are not scrolling through thousands of lines of grep -r output.

Combining both: find + grep#

If you need to search within a specific file type and --include is not flexible enough:

find . -name "*.php" -exec grep -l "eval(" {} \;

Finds .php files that contain eval( - a classic pattern for hunting down suspicious or malicious code.

The faster option: ripgrep (rg)#

In a large directory tree - especially with folders like node_modules or .git - grep -r slows down noticeably. ripgrep automatically skips what .gitignore excludes and scans in parallel, and is usually several times faster:

sudo apt install -y ripgrep    # Ubuntu/Debian
sudo dnf install -y ripgrep    # Rocky/AlmaLinux
rg "ERROR" /var/log/nginx/

The syntax is close to grep; the biggest differences are that it respects .gitignore/.ignore automatically and is recursive by default.

With Morpheus

"list every .log file under /var/log that changed in the last 24 hours"

"find lines containing 'connection refused' in the nginx logs"

Morpheus runs both of these in one request - you do not have to write find and grep separately.

Checklist#

  • [ ] Used find for a filename, grep -r for file content
  • [ ] Tried ripgrep if speed was an issue in a large tree (node_modules, .git)
  • [ ] Previewed with -print before an irreversible -exec rm