Linux Search & Comparison: Files, Content, and Differences

Finding files by metadata, querying text within codebase and logs, and comparing differences are essential skills for sysadmins and developers. This guide covers file discovery (find, locate, fd, which), text search (grep, ripgrep, ack, sed), and difference analysis (diff, cmp, comm, patch).


⚡ Quick Dive

1. Finding Files by Name & Metadata

Command Action Example
find <path> -name "<pattern>" Search recursively by filename find . -name "*.log"
find <path> -type f -size +100M Find regular files larger than 100MB find /var -type f -size +100M
find <path> -mtime -7 Find files modified in the last 7 days find /home -mtime -7
locate <pattern> Instant lookup using pre-built database locate nginx.conf
which <binary> Locate executable in user's $PATH which docker
fd -e md Modern fast file search by extension fd -e md

2. Searching Inside File Contents

Command Action Example
grep -rnI "<pattern>" <path> Recursive line-numbered text search ignoring binary grep -rnI "DB_PASSWORD" /etc/
grep -iE "(error|fatal)" <file> Case-insensitive extended regex search grep -iE "(error|fatal)" app.log
rg -i "<pattern>" Ultra-fast search respecting .gitignore (ripgrep) rg -i "TODO:" src/
sed -n '/pattern/p' <file> Print only lines matching pattern sed -n '/EXCEPTION/p' crash.log

3. Comparing Files & Applying Diffs

Command Action Example
diff -u <file1> <file2> Standard unified diff output diff -u nginx.conf nginx.conf.bak
diff -r -q <dir1> <dir2> Briefly report differing files between directories diff -rq /app/v1 /app/v2
cmp -b <file1> <file2> Byte-by-byte comparison for binary files cmp -b firmware_v1.bin firmware_v2.bin
comm -12 <file1> <file2> Show lines common to both sorted files comm -12 sorted_a.txt sorted_b.txt
patch <file> < diff.patch Apply a unified diff patch to a target file patch config.py < update.patch

📖 Extended Guide

1. Searching for Files

find — Exhaustive Real-Time Filesystem Search

find evaluates expressions top-down against live directory hierarchies.

Common Tests & Expressions
  • Name matching: -name "*.py" (case-sensitive) or -iname "*.py" (case-insensitive).
  • File types: -type f (regular file), -type d (directory), -type l (symlink), -type s (socket).
  • Size filters: -size +50M (greater than 50MB), -size -10k (less than 10KB), -size 0 (empty).
  • Time filters:
    • -mtime -7 (modified in last 7 days), -mtime +30 (modified over 30 days ago).
    • -mmin -60 (modified in last 60 minutes).
  • Permission & Owner: -perm 644, -user www-data, -group developers.
  • Depth limits: -maxdepth 2, -mindepth 1.
Actions & -exec Optimization
# Find and delete log files older than 30 days
find /var/log/app/ -type f -name "*.log" -mtime +30 -delete

# Execute a command once per file (\;)
find /var/www -type f -name "*.html" -exec chmod 644 {} \;

# Execute command batching multiple files at once for high performance ({}+)
find /var/www -type f -name "*.html" -exec chmod 644 {} +

# Prune (skip) directories like .git or node_modules
find . -path "*/node_modules" -prune -o -name "*.json" -print

locate & updatedb — Indexed Database Search

locate searches a pre-indexed database (/var/lib/mlocate/mlocate.db or plocate).

# Update the index manually
sudo updatedb

# Fast case-insensitive search
locate -i "docker-compose.yml"

Identifying Binaries: which, whereis, and type

  • which: Shows which binary would execute from $PATH.
  • whereis: Locates binary, source code, and man pages.
  • type -a (Shell Builtin): Identifies whether a command is an alias, shell builtin, function, or disk executable.
$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls

Modern Alternative: fd

fd is a fast, user-friendly alternative to find with colorized output and smart-case defaults.

# Find all markdown files ignoring .git
fd -e md

# Search directories matching "auth"
fd -t d auth

2. Searching File Contents

grep — Global Regular Expression Print

grep scans input line-by-line against regex patterns.

Key Options
  • -r, -R: Recursive directory search (-R follows symlinks).
  • -n: Print 1-indexed line numbers.
  • -I: Ignore binary files.
  • -i: Case-insensitive matching.
  • -v: Invert match (print non-matching lines).
  • -w: Match whole words only.
  • -l: Print filenames containing matches only.
  • -c: Print total match count per file.
  • -E: Extended regular expressions (enables |, +, ?, ()).
  • -F: Fixed string matching (disables regex for faster literal search).
  • -P: Perl-compatible regular expressions (PCRE).
Context Controls
  • -A <num>: Print <num> lines After the match.
  • -B <num>: Print <num> lines Before the match.
  • -C <num>: Print <num> lines of Context (both before & after).
# Inspect stack trace context around errors
grep -n -C 3 "NullPointerException" server.log

# Search IP addresses using PCRE
grep -P -o '\b\d{1,3}(\.\d{1,3}){3}\b' access.log

Modern Search: ripgrep (rg), ack, and ag

Feature grep -r ag (Silver Searcher) rg (ripgrep)
Speed Baseline Fast ⚡ Fastest (multithreaded Rust)
Respects .gitignore ❌ No ✅ Yes ✅ Yes
Skips Binary Files Only with -I ✅ Yes ✅ Yes (automatic)
Unicode Support Dependent on locale Limited Full UTF-8/UTF-16
# Search codebase with ripgrep
rg "export interface User" --type ts

# Search with ripgrep including hidden files and ignoring gitignore
rg --hidden --no-ignore "API_SECRET"

Stream Editing & Search with sed

sed transforms and filters text streams based on patterns.

# Print lines between line 20 and 40
sed -n '20,40p' error.log

# Search and replace in-place with backup
sed -i.bak 's/http:\/\/localhost/https:\/\/example.com/g' config.env

3. Comparing Files & Analyzing Differences

diff — Line-by-Line File Comparison

diff compares two files or directory trees.

Output Formats:
  1. Unified Format (-u): Industry standard format used in Git and patches.
  2. Side-by-Side (-y): Displays two columns with change markers (<, >, |).
  3. Context Format (-c): Shows lines of context around modifications.
# Standard unified diff
diff -u server.conf server.conf.new > server.patch

# Side-by-side diff with custom width
diff -y -W 120 file1.txt file2.txt

# Directory comparison ignoring whitespace
diff -ruN -w dir_v1/ dir_v2/

Applying Changes with patch

Apply changes generated by diff -u:

# Generate patch
diff -u original.py modified.py > feature.patch

# Apply patch to original
patch original.py < feature.patch

# Reverse/undo patch
patch -R original.py < feature.patch

Byte-Level Comparison: cmp

Used for binary files, images, compiled objects, and disk images:

# Compare binary files
$ cmp -l file1.bin file2.bin
1024  40  41    # Byte offset 1024 differs (octal 40 vs 41)

# Silent check for script conditions (exit code 0 if identical)
if cmp -s original.bin copy.bin; then
    echo "Files are identical"
fi

Sorted Set Operations: comm

Compares two sorted text files column-by-column:

  • Column 1: Lines unique to File 1
  • Column 2: Lines unique to File 2
  • Column 3: Lines common to both files
# Suppress column 1 & 2 to show ONLY lines present in BOTH files
comm -12 <(sort file1.txt) <(sort file2.txt)

# Show lines unique to file1
comm -23 <(sort file1.txt) <(sort file2.txt)