How to Find Files in Bash

How to Find Files in Bash

How to Find Files in Bash

There was a period early in my Linux journey where I’d just browse directories manually trying to remember where I put a file, which is a hilariously slow way to work once you know the find command exists. Finding files by name, type, size, modification date, or even content is one of those skills that quietly saves hours over time, and it’s worth learning properly rather than just memorizing one or two commands you copy-paste forever.

In this guide, I’ll cover find, locate, and grep (for searching file contents), with practical examples for each, plus how to combine them into more powerful one-liners.

The find Command Basics

find searches a directory tree recursively based on criteria you specify.

find /path/to/search -name "filename.txt"

This searches starting at /path/to/search for any file named exactly filename.txt.

Searching by Name

Exact Match

find . -name "report.txt"

The . means “start searching from the current directory.”

Case-Insensitive Search

find . -iname "report.txt"

Using Wildcards

find . -name "*.log"

This finds every file ending in .log, regardless of what comes before it. Remember to quote the pattern so Bash doesn’t try to expand the wildcard itself before passing it to find.

Searching by File Type

find . -type f -name "*.conf"
find . -type d -name "logs"

Other type options include -type l for symbolic links.

Searching by Size

find . -type f -size +100M
find . -type f -size -1k

Size units include c (bytes), k (kilobytes), M (megabytes), and G (gigabytes).

Searching by Modification Time

find . -type f -mtime -7
find . -type f -mtime +30

For more precision down to minutes:

find . -type f -mmin -60

Searching by Permissions

find . -type f -perm 644

This finds files with exactly 644 permissions (read/write for owner, read-only for group and others).

find / -type f -perm -4000

Searching by Owner

find /home -user alice

Finds all files owned by the user alice.

find / -group developers

Finds all files owned by the group developers.

Combining Multiple Conditions

You can combine conditions using logical operators.

AND (Default Behavior)

find . -type f -name "*.log" -size +10M

Multiple conditions listed together are implicitly ANDed — this finds .log files larger than 10MB.

OR

find . -name "*.log" -o -name "*.txt"

NOT

find . -type f -not -name "*.txt"

Finds all files except .txt files.

Executing Commands on Found Files

This is where find becomes genuinely powerful — you can run a command against every result.

find . -name "*.tmp" -exec rm {} \;

Breaking this down:

For better performance on large result sets, use + instead of \;, which batches multiple files into fewer command invocations:

find . -name "*.tmp" -exec rm {} +

A Safer Alternative: -exec With Confirmation

find . -name "*.tmp" -ok rm {} \;

Searching by File Content With grep

While find locates files based on metadata (name, size, date), grep searches inside file contents.

grep -r "TODO" /path/to/project

Case-Insensitive Content Search

grep -ri "error" /var/log/

Showing Line Numbers

grep -rn "function loadData" src/

Combining find and grep

find . -name "*.py" -exec grep -l "import requests" {} \;

This finds every Python file that imports the requests module. -l tells grep to print only the filenames of matches, not the matching lines themselves.

Using locate for Faster Searches

find searches the filesystem in real time, which can be slow on large systems. locate instead searches a prebuilt index, making it much faster.

locate report.txt

Before using it, make sure the index is updated:

sudo updatedb

The tradeoff is that locate won’t reflect very recent file changes until the index is refreshed, whereas find always reflects the current state of the filesystem.

Real-World Use Cases

Cleaning up temporary files:

find /tmp -type f -mtime +7 -exec rm {} \;

Removes temporary files older than 7 days, a common maintenance task on servers.

Finding large files eating disk space:

find / -type f -size +500M 2>/dev/null

The 2>/dev/null suppresses “permission denied” errors from directories you can’t access, keeping output clean.

Auditing world-writable files (a security check):

find / -type f -perm -0002 2>/dev/null

This finds files writable by anyone, which is often a red flag worth investigating.

Finding recently modified configuration files after a suspected breach:

find /etc -type f -mtime -1

Automation Example: Cleanup Script

#!/bin/bash

TARGET_DIR="/var/log/myapp"
DAYS_OLD=14

echo "Searching for log files older than $DAYS_OLD days in $TARGET_DIR..."

find "$TARGET_DIR" -type f -name "*.log" -mtime +$DAYS_OLD -print -exec rm {} \;

echo "Cleanup complete."

How it works internally:

  1. find searches $TARGET_DIR for .log files older than $DAYS_OLD days.
  2. -print shows each matched file before deleting it, so you get a log of what was removed.
  3. -exec rm {} \; deletes each matched file individually.
  4. This script could be scheduled with cron to run weekly, automatically keeping log directories from growing indefinitely.

Best Practices

Security Considerations

Optimization Tips

find . -maxdepth 2 -name "*.conf"

Troubleshooting Common Issues

“Permission denied” errors cluttering output: Redirect stderr with 2>/dev/null, but remember this hides real errors too, so use cautiously.

find seems to return nothing when you expect matches: Double-check your pattern is quoted ("*.log" not *.log), since an unquoted wildcard gets expanded by Bash itself before find ever sees it.

locate returns outdated results: Run sudo updatedb to refresh the index.

-exec command fails on filenames with spaces: Use {} combined with proper quoting or switch to -exec ... + instead of \;, which handles this more gracefully in most cases.

Frequently Asked Questions

What’s the difference between find and locate? find searches the filesystem live and reflects current state but can be slower. locate searches a prebuilt index, which is fast but may be slightly out of date.

Can find search file contents directly? Not on its own — combine it with grep using -exec for content-based searches.

Is find case-sensitive by default? Yes, use -iname instead of -name for case-insensitive matching.

How do I find files modified between two specific dates? Use -newer with a reference file, or combine -mtime conditions, or use find with -newermt for specific date strings (GNU find extension): find . -newermt "2026-01-01" ! -newermt "2026-02-01".

Common Mistakes to Avoid

Summary

Finding files efficiently in Bash comes down to mastering find for metadata-based searches (name, size, type, date, permissions) and grep for content-based searches, with locate as a fast alternative for simple filename lookups. Once you’re comfortable combining conditions and using -exec safely, you can automate cleanup tasks, security audits, and everyday file management directly from the terminal.

References

Exit mobile version