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
findfor a filename,grep -rfor file content - [ ] Tried
ripgrepif speed was an issue in a large tree (node_modules,.git) - [ ] Previewed with
-printbefore an irreversible-exec rm