Skip to main content

How to Find Files in Bash

• 5 min read
bash file operations find command search

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

MethodSyntaxBest ForComplexity
find -namefind . -name "*.txt"Simple name searchSimple
find -typefind . -type fFile/directory typeSimple
find -sizefind . -size +1MSize-based searchModerate
locatelocate filenameFast indexed searchSimple
grep -rgrep -r "text" .Content searchModerate

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).

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.

find . -name "*.txt"

The * wildcard matches any characters. This finds all .txt files recursively.

find . -iname "SCRIPT.sh"

The i before name makes the search case-insensitive. Matches script.sh, SCRIPT.SH, Script.Sh, etc.

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 . -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.