How to Find Files in Bash
Quick Answer: Find Files in Bash
To find files in Bash, use the find command: find . -name "*.txt". Use -type f for files, -type d for directories. Combine with -size, -mtime, -perm for advanced filtering. Always start from the correct directory.
Quick Comparison: File Finding Methods
| Method | Syntax | Best For | Complexity |
|---|---|---|---|
| find -name | find . -name "*.txt" | Simple name search | Simple |
| find -type | find . -type f | File/directory type | Simple |
| find -size | find . -size +1M | Size-based search | Moderate |
| locate | locate filename | Fast indexed search | Simple |
| grep -r | grep -r "text" . | Content search | Moderate |
Bottom line: Use find -name for name searching, grep -r for content searching.
Method 1: Find by Filename
The most common use of find is searching for files by name. The -name option matches filenames exactly or with wildcards. Always start from the correct directory (. for current, / for root).
Basic Name Search
find . -name "script.sh"
This searches the current directory and all subdirectories for a file named exactly script.sh. Use . for current directory, or specify a path like /home/user/ to start from there.
Wildcard Pattern Search
find . -name "*.txt"
The * wildcard matches any characters. This finds all .txt files recursively.
Case-Insensitive Search
find . -iname "SCRIPT.sh"
The i before name makes the search case-insensitive. Matches script.sh, SCRIPT.SH, Script.Sh, etc.
When to Use Name Search
Use -name when:
- Looking for specific files by extension
- Searching by filename pattern
- You know approximately what the file is named
- Recursive search through directories needed
Performance Note
Name search is relatively fast. It’s one of the most efficient find operations.
Method 2: Find by Type
Restrict results to files, directories, or symbolic links using the -type option. This prevents getting unexpected results.
Find Only Regular Files
find . -type f
The f means “regular files only”—excludes directories, links, and other special files. Essential when you only want files to process.
Find Only Directories
find . -type d
The d matches directories only. Useful when reorganizing folder structures.
Find Symbolic Links
find . -type l
The l finds symbolic links (shortcuts). Useful for finding broken links or understanding symbolic link structure.
Combine Type with Name
find . -type f -name "*.log"
This finds only regular files ending in .log, excluding directories named like foo.log (if somehow they exist).
When to Use Type Filter
Use -type when:
- Avoiding directories in results
- Ensuring only files are processed
- Searching for specific link types
- Preventing errors in loops
Method 3: Find by File Size
Filter results by file size using -size option. Great for finding large files eating disk space or finding empty files.
Find Files Larger Than a Threshold
find . -type f -size +100M
The + means “greater than”. This finds files larger than 100MB. Sizes can be in k (kilobytes), M (megabytes), or G (gigabytes).
Find Files Smaller Than a Threshold
find . -type f -size -10k
The - means “less than”. This finds files smaller than 10KB.
Find Files of Exact Size
find . -type f -size 5M
Without + or -, finds files exactly 5MB (or close to it).
Find Empty Files
find . -type f -empty
The -empty flag finds zero-length files. Useful for cleanup.
When to Use Size Filter
Use -size when:
- Disk space investigation (finding large files)
- Cleanup operations (finding empty files)
- Backup optimization
- Data migration decisions
Method 4: Find by Modification Time
The -mtime option filters by when files were last modified. Useful for cleanup, backup, and log rotation.
Find Recently Modified Files
find . -type f -mtime -7
The -7 means “less than 7 days ago”—finds files modified in the last week.
Find Old Files
find . -type f -mtime +30
The +30 means “more than 30 days ago”—finds files not touched for a month.
Find Files Modified on a Specific Day
find . -type f -mtime 1
Exactly 1 finds files modified exactly 1 day ago (24-48 hours).
Understanding mtime Precision
Note that -mtime measures complete 24-hour periods. Use -mmin for minute-level precision:
# Modified in last hour
find . -type f -mmin -60
# Modified in last 30 minutes
find . -type f -mmin -30
When to Use Time Filter
Use -mtime when:
- Log cleanup (removing old logs)
- Backup strategies (only backing up recent files)
- Finding active projects
- System maintenance
Method 5: Find by Permissions
Filter by file permissions using -perm or -executable. Useful for security audits and permission corrections.
Find Executable Files
find . -type f -executable
Finds all executable files (shell scripts, binaries, etc.).
Find Files with Specific Permissions
find . -type f -perm 644
Finds files with exact permissions 644 (rw-r—r—).
Find Files Readable by Owner
find . -type f -readable
Finds files readable by the current user.
Find Files Writable by Owner
find . -type f -writable
Finds files the current user can modify.
When to Use Permission Filter
Use -perm when:
- Security audits
- Finding wrongly-permissioned files
- Permission corrections
- Script verification
Practical Examples
Example 1: Find All Log Files and Their Sizes
#!/bin/bash
echo "Log files in /var/log and their sizes:"
find /var/log -type f -name "*.log" -exec ls -lh {} \;
echo ""
echo "Total space used by log files:"
find /var/log -type f -name "*.log" -exec du -ch {} \; | tail -1
Shows detailed information about all log files and total space used.
Example 2: Find and List Large Files
#!/bin/bash
# Find files larger than 100MB
echo "Large files (>100MB):"
find / -type f -size +100M 2>/dev/null | while read file; do
size=$(du -h "$file" | cut -f1)
echo "$size - $file"
done | sort -rh | head -20
Lists top 20 largest files on the system.
Example 3: Find Recently Modified Files for Backup
#!/bin/bash
# Find files modified in last day
backup_dir="/backup"
mkdir -p "$backup_dir"
echo "Backing up files modified in last 24 hours..."
find . -type f -mtime -1 | while read file; do
mkdir -p "$backup_dir/$(dirname "$file")"
cp -p "$file" "$backup_dir/$file"
done
echo "Backup complete"
Backs up only recent files, saving space.
Example 4: Find Empty Files and Remove Them
#!/bin/bash
# Find and list empty files first
echo "Empty files found:"
find . -type f -empty
# Ask before deleting
read -p "Delete empty files? (y/n) " -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
find . -type f -empty -delete
echo "Empty files deleted"
fi
Safe deletion of empty files with confirmation.
Example 5: Find Duplicate Files by Size
#!/bin/bash
# Find files with same size (potential duplicates)
echo "Potential duplicate files (by size):"
find . -type f -exec ls -l {} \; | \
awk '{print $5, $NF}' | \
sort | \
uniq -d | \
sort -rn
Lists files with identical sizes—good first step in finding duplicates.
Example 6: Find and Rename Files
#!/bin/bash
# Find .bak files and rename to .backup
echo "Renaming .bak files to .backup..."
find . -type f -name "*.bak" | while read file; do
newfile="${file%.bak}.backup"
mv "$file" "$newfile"
echo "Renamed: $file -> $newfile"
done
Uses find with a loop for per-file processing.
Example 7: Find Files Modified Before a Specific Date
#!/bin/bash
# Create a reference file with a timestamp
touch -d "2024-12-01" /tmp/date_ref
# Find files older than that date
echo "Files modified before 2024-12-01:"
find . -type f -not -newer /tmp/date_ref
rm /tmp/date_ref
Uses the -newer operator with a reference file to find files before a date.
Example 8: Find and Execute Commands
#!/bin/bash
# Count lines in all .sh files
echo "Total lines in shell scripts:"
find . -type f -name "*.sh" -exec wc -l {} + | tail -1
# Or with more control per file
find . -type f -name "*.sh" | while read script; do
lines=$(wc -l < "$script")
printf "%5d %s\n" "$lines" "$script"
done | sort -rn
Uses find to execute commands on matching files.
Quick Reference
# Find by name
find . -name "*.txt"
find . -iname "*.TXT" # Case-insensitive
# Find by type
find . -type f # Regular files only
find . -type d # Directories only
find . -type l # Symbolic links
# Find by size
find . -type f -size +100M # Larger than 100MB
find . -type f -size -10k # Smaller than 10KB
find . -type f -empty # Empty files
# Find by time
find . -type f -mtime -7 # Modified in last 7 days
find . -type f -mtime +30 # Not modified for 30+ days
find . -type f -mmin -60 # Modified in last hour
# Find by permissions
find . -type f -executable # Executable files
find . -type f -readable # Readable by user
find . -type f -writable # Writable by user
# Find with actions
find . -name "*.log" -delete # Delete
find . -name "*.txt" -exec cat {} \; # Execute command
find . -name "*.log" | wc -l # Count matches
# Complex searches
find . -type f \( -name "*.log" -o -name "*.bak" \) # Multiple patterns
find . -type f -name "*.txt" -size +1M # Multiple conditions
Important Considerations
Always Quote Patterns
# CORRECT
find . -name "*.txt"
# WRONG: Shell expands * before find sees it
find . -name *.txt # Can cause unexpected behavior
Use -type f Carefully
# Wrong: might match directories too
find . -name "*.log"
# Better: restrict to files
find . -type f -name "*.log"
Test Before Destructive Operations
# Step 1: List what would be affected
find . -name "*.bak"
# Step 2: If output looks right, then delete
find . -name "*.bak" -delete
Avoid Complex Pipes with find
# Slower: pipes each result separately
find . -name "*.txt" | xargs wc -l
# Better: use find's built-in actions
find . -name "*.txt" -exec wc -l {} + # The + means "batch"
Summary
The find command is incredibly powerful for locating files. Start with simple name searches, add type filters to restrict to files, and combine with size or time filters for advanced queries. Always test your find command before using it with destructive operations like -delete. Remember to quote your patterns and use -type f to avoid accidentally matching directories.