GNU findutils is the backbone of file searching and batch processing on Linux and Unix systems. The package includes four core commands — find, locate, updatedb, and xargs — that handle everything from locating files by name to executing complex batch operations across thousands of files. This cheatsheet covers every major use case across Linux, macOS, and Windows, plus a mapping to free web-based alternatives at findutils.com for when you need a browser-based solution.
Whether you're a sysadmin hunting down rogue log files, a developer cleaning up build artifacts, or a security engineer auditing file permissions — this is your single reference for all findutils operations.
GNU findutils is a collection of four command-line utilities that search for and process files on Unix-like operating systems. Every major Linux distribution includes findutils by default, and macOS ships with BSD versions of the same commands. Here's what each command does:
| Command | Purpose | Speed | Requires Root? |
|---|---|---|---|
find | Search files in real-time by traversing directories | Slower (live scan) | No (but some dirs need it) |
locate | Search files from a pre-built database | Very fast (database lookup) | No |
updatedb | Rebuild the database used by locate | N/A (maintenance) | Yes (usually) |
xargs | Build and execute commands from standard input | N/A (command builder) | Depends on command |
Findutils comes pre-installed on most systems, but here's how to install or update it on each platform.
sudo apt install findutils # Fedora/RHEL sudo dnf install findutils # Arch Linux sudo pacman -S findutils # Check version find --version
macOS ships with BSD find, which has slightly different flags. To get GNU findutils (recommended for full compatibility):
# Install via Homebrew brew install findutils # GNU versions are prefixed with 'g' gfind --version # GNU find gxargs --version # GNU xargs glocate --version # GNU locate
Tip: Add GNU findutils to your PATH to use them without the g prefix:
export PATH="/opt/homebrew/opt/findutils/libexec/gnubin:$PATH"
# Option 1: WSL (Windows Subsystem for Linux) wsl sudo apt install findutils # Option 2: Git Bash (ships with find and xargs) # Already included — just open Git Bash # Option 3: Cygwin # Select findutils during Cygwin setup # Option 4: MSYS2 pacman -S findutils # Windows native equivalent where /R C:\ filename.txt # Similar to find -name dir /S /B *.txt # Recursive file listing
find Command — Complete CheatsheetThe find command is the most powerful and versatile tool in findutils. It searches the filesystem in real-time, applying filters and executing actions on matches.
find [path] [options] [expression]
| Command | Description |
|---|---|
find . -name "file.txt" | Find exact filename (case-sensitive) |
find . -iname "file.txt" | Find filename (case-insensitive) |
find . -name "*.json" | Find all JSON files |
find . -name "*.log" -o -name "*.tmp" | Find .log OR .tmp files |
find / -name "nginx.conf" | Search entire system for nginx.conf |
find . -not -name "*.txt" | Find all files EXCEPT .txt |
find . -name "report-[0-9]*" | Find files matching glob pattern |
| Command | Description |
|---|---|
find . -type f | Find regular files only |
find . -type d | Find directories only |
find . -type l | Find symbolic links only |
find . -type f -name "*.sh" | Find shell scripts (files only) |
find . -type d -name "node_modules" | Find all node_modules directories |
find . -type f -empty | Find empty files |
find . -type d -empty | Find empty directories |
| Command | Description |
|---|---|
find . -size +100M | Files larger than 100 MB |
find . -size -1k | Files smaller than 1 KB |
find . -size +1G | Files larger than 1 GB |
find . -size 0 | Zero-byte files |
find . -size +50M -size -200M | Files between 50-200 MB |
find /var/log -size +500M -type f | Large log files |
Size suffixes: c (bytes), k (kilobytes), M (megabytes), G (gigabytes)
| Command | Description |
|---|---|
find . -mtime -7 | Modified in the last 7 days |
find . -mtime +30 | Modified more than 30 days ago |
find . -mmin -60 | Modified in the last 60 minutes |
find . -atime -1 | Accessed in the last 24 hours |
find . -ctime -7 | Status changed in the last 7 days |
find . -newer reference.txt | Modified after reference.txt |
find . -mtime +365 -type f | Files not modified in over a year |
Time units: -mtime (days), -mmin (minutes), -atime (access time), -ctime (change time)
| Command | Description |
|---|---|
find . -perm 644 | Files with exact permission 644 |
find . -perm -u+x | Files executable by owner |
find . -perm /o+w | Files writable by others (security risk) |
find / -perm -4000 | Find SUID files (security audit) |
find . -user www-data | Files owned by www-data |
find . -group developers | Files owned by group "developers" |
find . -nouser | Files with no valid owner |
find . -nogroup | Files with no valid group |
| Command | Description |
|---|---|
find . -maxdepth 1 -type f | Only current directory (no recursion) |
find . -maxdepth 2 -name "*.txt" | Current dir + 1 level deep |
find . -mindepth 2 -type f | Skip current dir, start 2 levels deep |
find . -maxdepth 3 -mindepth 2 | Only 2-3 levels deep |
This is where find becomes incredibly powerful — executing commands on every match.
| Command | Description |
|---|---|
find . -name "*.tmp" -delete | Delete all .tmp files |
find . -name "*.log" -exec rm {} \; | Delete using exec (one by one) |
find . -name "*.log" -exec rm {} + | Delete using exec (batched, faster) |
find . -type f -exec chmod 644 {} + | Set permissions on all files |
find . -type d -exec chmod 755 {} + | Set permissions on all directories |
find . -name "*.txt" -exec grep -l "error" {} + | Find .txt files containing "error" |
find . -name "*.jpg" -exec cp {} /backup/ \; | Copy all JPGs to backup |
find . -name "*.bak" -exec mv {} /archive/ \; | Move all .bak files to archive |
find . -type f -exec ls -lh {} + | sort -k5 -h | List files sorted by size |
| Command | Description |
|---|---|
find . -path ./node_modules -prune -o -name "*.js" -print | Skip node_modules |
find . -not -path "./.git/*" -name "*.py" | Exclude .git directory |
find . -path ./vendor -prune -o -path ./node_modules -prune -o -type f -print | Skip multiple dirs |
| Command | Description |
|---|---|
find . -name "*.js" -and -size +100k | AND condition (both must match) |
find . -name "*.jpg" -or -name "*.png" | OR condition (either matches) |
find . -not -name "*.log" | NOT condition (negate) |
find . \( -name "*.css" -o -name "*.js" \) -mtime -7 | Grouped OR with time filter |
# Find duplicate files by size (potential duplicates)
find . -type f -exec ls -lS {} + | awk '{print $5, $NF}' | sort -n | uniq -d -w 10
# Find and count files by extension
find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -20
# Find files modified today
find . -type f -daystart -mtime 0
# Find broken symlinks
find . -xtype l
# Find largest 10 directories
find . -type d -exec du -sh {} + 2>/dev/null | sort -rh | head -10
# Find world-writable files (security audit)
find / -type f -perm -0002 -ls 2>/dev/null
# Find files with specific content and replace
find . -name "*.txt" -exec sed -i 's/old/new/g' {} +
# Find recently modified config files
find /etc -name "*.conf" -mmin -30 -type flocate Command — Fast File SearchThe locate command searches a pre-built database of filenames, making it 10-100x faster than find for simple name searches. The tradeoff: it doesn't see files created since the last database update.
| Command | Description |
|---|---|
locate filename.txt | Find files matching "filename.txt" |
locate -i README | Case-insensitive search |
locate "*.json" | Find all JSON files in database |
locate -c "*.pdf" | Count matching files (don't list) |
locate -l 10 "*.log" | Show only first 10 results |
locate -r '\.py$' | Use regex pattern matching |
locate --existing "*.conf" | Only show files that still exist |
locate -S | Show database statistics |
macOS uses a different locate implementation:
# Update the database on macOS sudo /usr/libexec/locate.updatedb # Or with GNU locate (from Homebrew findutils) gupdatedb glocate filename
Windows doesn't have locate, but you can use:
# Windows Search from command line where /R C:\ *.json # PowerShell equivalent Get-ChildItem -Path C:\ -Recurse -Filter "*.json" -ErrorAction SilentlyContinue # Using Everything (third-party, very fast) es.exe "*.json"
updatedb Command — Database Maintenanceupdatedb rebuilds the file database used by locate. Most systems run it automatically via a daily cron job.
| Command | Description |
|---|---|
sudo updatedb | Update the entire database |
updatedb --localpaths='/home /var' | Only index specific paths |
updatedb --prunepaths='/tmp /proc /sys' | Exclude specific paths |
updatedb --prunefs='NFS nfs' | Exclude filesystem types |
updatedb --output=/tmp/mydb.db | Write to custom database file |
locate -d /tmp/mydb.db pattern | Use custom database for search |
The default configuration is at /etc/updatedb.conf:
# Common /etc/updatedb.conf settings PRUNE_BIND_MOUNTS="yes" PRUNEPATHS="/tmp /var/spool /media /mnt" PRUNEFS="NFS nfs nfs4 rpc_pipefs afs binfmt_misc"
xargs Command — Batch Command Builderxargs reads items from standard input and executes a command with those items as arguments. It's the glue that makes find pipelines truly powerful.
| Command | Description |
|---|---|
find . -name "*.log" | xargs rm | Delete found files |
find . -name "*.txt" | xargs grep "error" | Search content in found files |
find . -name "*.jpg" | xargs -I {} cp {} /backup/ | Copy each file (with placeholder) |
cat urls.txt | xargs wget | Download all URLs from file |
echo "1 2 3 4 5" | xargs -n 2 | Group args in pairs |
find . -name "*.gz" | xargs -P 4 gunzip | Parallel decompression (4 jobs) |
This is the #1 gotcha with xargs. Always use null-delimited input for safety:
# SAFE: Use -print0 and -0 together
find . -name "*.txt" -print0 | xargs -0 rm
# SAFE: Use -I with placeholder
find . -name "*.txt" | xargs -I {} mv {} /backup/
# UNSAFE: Will break on spaces in filenames
find . -name "*.txt" | xargs rm # DON'T DO THIS| Flag | Description | Example |
|---|---|---|
-0 | Input delimited by null chars | find . -print0 | xargs -0 ls |
-I {} | Replace placeholder with each item | xargs -I {} cp {} /dest/ |
-n N | Max N arguments per command | xargs -n 1 echo |
-P N | Run N parallel processes | xargs -P 8 gzip |
-p | Prompt before each execution | xargs -p rm |
-t | Print command before executing | xargs -t chmod 644 |
-L N | Max N lines per command | xargs -L 1 command |
--max-procs | Same as -P (GNU) | xargs --max-procs=4 |
--no-run-if-empty | Skip if no input (GNU) | xargs --no-run-if-empty rm |
# Parallel file compression (8 cores)
find . -name "*.log" -print0 | xargs -0 -P 8 gzip
# Batch rename files
find . -name "*.jpeg" | xargs -I {} bash -c 'mv "$1" "${1%.jpeg}.jpg"' _ {}
# Download URLs in parallel
cat urls.txt | xargs -P 5 -I {} wget -q {}
# Count lines in all Python files
find . -name "*.py" | xargs wc -l | tail -1
# Run eslint on changed files only
git diff --name-only -- '*.js' | xargs eslint
# Batch image resize with ImageMagick
find . -name "*.png" -print0 | xargs -0 -P 4 -I {} convert {} -resize 50% {}Not every command works the same on every OS. Here's a quick reference:
| Operation | Linux | macOS (BSD) | macOS (GNU) | Windows (PowerShell) |
|---|---|---|---|---|
| Find by name | find . -name "*.txt" | find . -name "*.txt" | gfind . -name "*.txt" | Get-ChildItem -Recurse -Filter *.txt |
| Case-insensitive | find . -iname "*.txt" | find . -iname "*.txt" | gfind . -iname "*.txt" | Get-ChildItem -Recurse -Filter *.txt (default) |
| Find by size | find . -size +100M | find . -size +100M | gfind . -size +100M | Get-ChildItem -Recurse | Where {$_.Length -gt 100MB} |
| Find by date | find . -mtime -7 | find . -mtime -7 | gfind . -mtime -7 | Get-ChildItem -Recurse | Where {$_.LastWriteTime -gt (Get-Date).AddDays(-7)} |
| Delete found | find . -name "*.tmp" -delete | find . -name "*.tmp" -delete | gfind . -name "*.tmp" -delete | Get-ChildItem -Recurse -Filter *.tmp | Remove-Item |
| Locate file | locate file | locate file | glocate file | where /R C:\ file |
| Update DB | sudo updatedb | sudo /usr/libexec/locate.updatedb | gupdatedb | N/A |
| Null-safe xargs | xargs -0 | xargs -0 | gxargs -0 | ForEach-Object {} |
Many operations that traditionally require find + command-line tools can now be done instantly in the browser. This table maps common find + exec/xargs pipelines to their free web-based equivalents on findutils.com — no terminal required.
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -name "*.json" -exec python -m json.tool {} \; | Format/beautify JSON files | JSON Formatter |
find . -name "*.json" -exec jq -c '.' {} \; | Minify JSON files | JSON Minifier |
find . -name "*.json" -exec diff {} \; | Compare JSON files | JSON Comparer |
find . -name "*.html" -exec tidy -i {} \; | Format HTML files | HTML Formatter |
find . -name "*.xml" -exec xmllint --format {} \; | Format XML files | XML Formatter |
find . -name "*.sql" -exec sqlformat {} \; | Format SQL files | SQL Formatter |
find . -name "*.css" -exec cleancss {} \; | Minify CSS files | CSS Minifier |
find . -name "*.yaml" -exec yamllint {} \; | Validate YAML files | YAML Validator |
find . -name "*.md" -exec grip {} \; | Preview Markdown | Markdown Previewer |
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -name "*.csv" | xargs csvjson | Convert CSV to JSON | CSV to JSON |
find . -name "*.json" | xargs json2csv | Convert JSON to CSV | JSON to CSV |
find . -name "*.json" -exec yq -p json -o yaml {} \; | Convert JSON to YAML | JSON-YAML Converter |
find . -name "*.xml" -exec xml2json {} \; | Convert XML to JSON | XML to JSON |
find . -name "*.json" -exec json2xml {} \; | Convert JSON to XML | JSON to XML |
find . -name "*.html" | xargs html2md | Convert HTML to Markdown | HTML to Markdown |
find . -name "*.csv" | xargs xlsx | Convert CSV to Excel | CSV to Excel |
find . -name "*.xlsx" | xargs csv-export | Convert Excel to CSV | Excel to CSV |
find . -name "*.docx" | xargs libreoffice --convert-to pdf | Convert Word to PDF | Word to PDF |
find . -name "*.pptx" | xargs libreoffice --convert-to pdf | Convert PPTX to PDF | PPTX to PDF |
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -type f -exec md5sum {} + | Generate MD5 hashes | MD5 Hash Generator |
find . -type f -exec sha256sum {} + | Generate SHA-256 hashes | SHA-256 Hash Generator |
find . -type f -exec sha256sum {} + | diff - checksums.txt | Compare file hashes | Hash Comparison Tool |
find . -name "*.jpg" -exec exiftool -all= {} + | Strip EXIF metadata from images | EXIF Remover |
find . -name "*.pem" -exec openssl x509 -text {} \; | Inspect SSL certificates | SSL Certificate Checker |
find . -name "*.jwt" -exec jwt decode {} \; | Decode JWT tokens | JWT Decoder |
find . -type f -exec openssl enc -aes-256-cbc {} \; | Encrypt files | Text Encryption |
find / -perm -4000 -type f -ls | Security audit (SUID files) | Security Headers Analyzer |
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -name "*.jpg" | xargs -P 4 convert -resize 800x | Batch resize images | Image Resizer |
find . -name "*.png" | xargs -P 4 pngquant --quality=65-80 | Compress images | Image Compressor |
find . -name "*.png" | xargs -I {} convert {} {}.jpg | Convert image formats | Image Converter |
find . -name "*.mp4" | xargs ffmpeg -i {} -an audio.mp3 | Extract audio from video | Video to Audio |
find . -name "*.mp4" | xargs ffmpeg -t 5 -vf "fps=10" | Convert video to GIF | Video to GIF |
find . -name "*.png" | xargs base64 | Convert images to Base64 | Image to Base64 |
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -name "*.txt" | xargs wc -w | Count words in files | Word Counter |
find . -name "*.txt" | xargs wc -c | Count characters in files | Character Counter |
find . -name "*.txt" -exec grep -E "pattern" {} + | Regex search across files | Regex Tester |
find . -name "*.txt" -exec diff {} \; | Compare text files | Diff Checker |
find . -name "*.md" -exec cat {} + | wc -w | Calculate reading time | Reading Time Estimator |
find . -name "*.txt" -exec sort {} \; | Sort lines in files | Text Line Sorter |
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -name "*.pdf" | xargs pdfunite output.pdf | Merge PDF files | PDF Merger |
find . -name "*.pdf" -exec pdfseparate {} page-%d.pdf \; | Split PDF pages | PDF Split |
find . -name "*.pdf" | xargs gs -dPDFSETTINGS=/ebook | Compress PDFs | PDF Compress |
find . -name "*.pdf" -exec pdftk {} cat 1-endeast output rotated.pdf \; | Rotate PDF pages | PDF Rotate |
| CLI Command | What It Does | Web Alternative |
|---|---|---|
find . -name "*.ts" -exec quicktype --src {} \; | Generate TypeScript types from JSON | JSON to TypeScript |
find . -name "*.json" -exec jsonschema {} \; | Validate JSON Schema | JSON Schema Validator |
find . -name "*.json" -exec jq '.' {} \; | Query JSON with jq | jq Playground |
find . -name "package.json" -exec cat {} \; | View CSV data | CSV Viewer |
find . -name "*.har" -exec har2curl {} \; | Convert HAR to cURL | HAR to cURL |
find . -name "*.json" -exec json-diff {} \; | Diff JSON files side by side | JSON Diff |
echo "timestamp" | date -d @ | Convert Unix timestamps | Unix Timestamp |
find . -name "*.json" -exec cat {} | base64 \; | Encode/decode Base64 | Base64 Encoder |
find . -name "*.json" -exec jsonpath {} '$.key' | Query JSON paths | JSON Path Finder |
Both command-line findutils and browser-based tools have their place. Here's a decision matrix:
| Scenario | Best Choice | Why |
|---|---|---|
| Processing 1,000+ files in batch | CLI (find + xargs) | Automation and speed at scale |
| Quick one-off formatting | Web tool | No setup, instant results |
| Automated CI/CD pipeline | CLI | Scriptable, repeatable |
| Sharing results with non-technical team | Web tool | No terminal needed |
| Files already on your server | CLI | No upload required |
| Sensitive data you can't upload | Web tool (findutils.com) | Client-side processing, nothing leaves your browser |
| Complex regex across many files | CLI (find + grep) | Raw speed |
| Testing a single regex pattern | Regex Tester | Visual feedback, match highlighting |
| Comparing two JSON configs | JSON Comparer | Visual diff, side-by-side view |
| Batch image resize for production | CLI (find + convert) | Scriptable |
| Quick image resize for social media | Image Resizer | Preset dimensions, instant preview |
FindUtils.com processes everything client-side in your browser — nothing is uploaded to servers. This makes web tools a safe choice even for sensitive data like API keys, configuration files, or private documents.
# WRONG — shell expands the glob before find sees it find . -name *.txt # CORRECT — quotes prevent premature expansion find . -name "*.txt"
# WRONG — breaks on "My Document.txt" find . -name "*.txt" | xargs rm # CORRECT — null-delimited, handles any filename find . -name "*.txt" -print0 | xargs -0 rm
# SLOW — spawns one process per file
find . -name "*.log" -exec grep "error" {} \;
# FAST — batches files into fewer processes
find . -name "*.log" -exec grep "error" {} +# SLOW — searches inside .git, node_modules, etc. find . -name "*.js" # FAST — skips heavy directories find . -path ./node_modules -prune -o -path ./.git -prune -o -name "*.js" -print
# BAD — indexes /tmp, /proc, network mounts sudo updatedb # GOOD — exclude transient and network paths sudo updatedb --prunepaths="/tmp /proc /sys /mnt /media /run"
Copy this section and pin it to your terminal:
# =================== FIND ESSENTIALS ===================
find . -name "*.ext" # Find by name
find . -iname "*.ext" # Case-insensitive
find . -type f -size +100M # Large files
find . -mtime -7 -type f # Modified last 7 days
find . -name "*.tmp" -delete # Delete matches
find . -name "*.js" -exec CMD {} + # Execute on matches
find . -print0 | xargs -0 CMD # Safe piping
# =================== LOCATE ESSENTIALS ==================
sudo updatedb # Refresh database
locate -i "filename" # Fast case-insensitive search
locate -c "*.pdf" # Count matches
locate -r '\.conf$' # Regex search
# =================== XARGS ESSENTIALS ===================
find . -print0 | xargs -0 CMD # Null-safe execution
cmd | xargs -I {} echo {} # Placeholder mode
cmd | xargs -P 4 -n 1 CMD # 4 parallel processes
cmd | xargs -p CMD # Prompt before eachQ1: What is GNU findutils?
A: GNU findutils is a package of four command-line utilities — find, locate, updatedb, and xargs — used to search for files and execute batch commands on Unix-like operating systems. It comes pre-installed on virtually every Linux distribution and is available for macOS via Homebrew and Windows via WSL or Git Bash.
Q2: What is the difference between find and locate?
A: find searches the filesystem in real-time by traversing directories, making it slower but always up-to-date. locate searches a pre-built database of filenames, making it 10-100x faster but potentially missing recently created files. Use updatedb to refresh the locate database.
Q3: Does macOS have findutils?
A: macOS ships with BSD versions of find and xargs, which have slightly different flags than GNU versions. To get full GNU findutils compatibility, install via Homebrew with brew install findutils. The GNU versions are available as gfind, glocate, gupdatedb, and gxargs.
Q4: How do I use find on Windows?
A: Windows doesn't include GNU findutils natively. Your best options are: WSL (Windows Subsystem for Linux) which gives you full Linux commands, Git Bash which includes find and xargs, or PowerShell's Get-ChildItem cmdlet which provides similar functionality. For a no-install alternative, findutils.com offers 250+ free browser-based tools for file processing.
Q5: Is findutils.com related to GNU findutils? A: FindUtils.com (findutils.com) is a website offering 250+ free browser-based utility tools that accomplish many of the same tasks as GNU findutils command-line pipelines — such as formatting JSON, converting file formats, hashing data, and processing images — without requiring a terminal. All processing happens client-side in your browser for maximum privacy.
Q6: How do I handle filenames with spaces in find and xargs?
A: Always use the -print0 flag with find and the -0 flag with xargs. This uses null characters instead of newlines as delimiters, safely handling any filename regardless of spaces or special characters: find . -name "*.txt" -print0 | xargs -0 rm.
Q7: What is the fastest way to find files on Linux?
A: For one-time searches, use locate (after running updatedb) — it's 10-100x faster than find because it queries a database. For searches that need to be 100% current or apply complex filters (size, permissions, modification time), use find. For web-based file processing without any command-line setup, use the free tools at findutils.com.