---
title: "Find"
description: "Complete find reference with file searching, filtering by type/size/time, permissions, advanced operations, and practical examples for locating files"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/cheatsheets/find
---

# Find

## Best Practices for Find Command Usage

- **Always quote patterns** to prevent shell expansion of special characters
- **Use -type f first** in find expressions for optimal performance
- **Prune heavy directories early** like node_modules, .git, .venv
- **Use -maxdepth** to limit search depth and improve performance
- **Test commands first** with -ls or -printf before using -delete
- **Use + instead of \;** with exec for better performance on many files
- **Suppress permission errors** with 2>/dev/null for cleaner output
- **Combine multiple criteria** to create efficient targeted searches
- **Use -xdev** to skip other filesystems when needed
- **Consider locate command** for quick name-only searches (faster than find)

## Common Errors and Solutions

- **error: "Permission denied"** → Use 2>/dev/null to suppress or run with sudo
- **error: "No such file or directory"** → Verify path exists and is readable
- **error: "Unexpected operator or missing operand"** → Check parentheses are escaped: \\( \\)
- **error: "Syntax error near token"** → Verify \\; or + is present after -exec
- **error: "Find is too slow"** → Use -maxdepth, -prune, and -type filters
- **error: "Deleted wrong files accidentally"** → Always preview with find first!
- **error: "Pattern not matching expected files"** → Test pattern with -ls before -delete
- **error: "xtype/executable not recognized"** → Use newer GNU find; some options are GNU-specific

---

ref: https://man7.org/linux/man-pages/man1/find.1.html

## Getting Started

Introduction to find command and basic concepts

### What is Find

Understanding find command and its purpose for filesystem searching

**Keywords:** find, search, filesystem, files, directory

#### Find command overview and basic syntax

```bash
# Find command: search filesystem for files matching criteria
# Syntax: find [path] [options] [expression]

# Key advantages:
# - Search by name, size, type, time, permissions
# - Walk directory trees recursively
# - Execute commands on found files
# - Filter by file properties
# - Combine multiple criteria with logical operators

# Basic structure:
# find /search/path -name "pattern"
# find . -type f -size +1M
# find /var/log -mtime +30
```

_exec_
```bash
find /home -maxdepth 2 -type d 2>/dev/null | head -5
```

_output_
```bash
/home
/home/user
/home/user/Documents
/home/user/Downloads
/home/user/Desktop
```

Find walks the filesystem tree starting from the specified path, showing found items that match criteria.

- Find searches recursively by default
- -maxdepth limits directory traversal depth
- Returns full paths to found files
- Redirect stderr (2>/dev/null) to hide permission errors

#### Find vs other search tools

```bash
# Compare find with similar tools:
# find: Search filesystem by name, size, type, time, permissions
# locate: Fast search using pre-built database
# grep: Search within file contents (text)
# ls: List directory contents (no recursive search)

# Use find when you need:
# - Recursive filesystem search
# - Filter by file properties (size, type, time, permissions)
# - Execute commands on found files
# - Complex search criteria
# - Real-time search (database not needed)
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -name "*.tmp" 2>/dev/null | wc -l
```

_output_
```bash
3
```

Find is ideal for complex searches combining multiple criteria like file type, name pattern, and location.

- Find is more flexible than locate for custom criteria
- Slower than locate but more current
- Can execute actions on matched files
- Better for scripts and automation

**Best practices:**

- Use -maxdepth to limit search depth and improve performance
- Suppress permission errors with 2>/dev/null
- Protect patterns with quotes to prevent shell expansion
- Combine criteria for efficient searches

**Common errors:**

- **Permission denied**: Use 2>/dev/null to suppress permission errors or run with elevated privileges

### Installation and Setup

Installing and verifying find functionality on different systems

**Keywords:** install, setup, version, verify, test

#### Verify find installation

```bash
# Check if find is installed
which find

# Display find version
find --version

# Show find help
find --help | head -20
```

_exec_
```bash
which find && find --version | head -1
```

_output_
```bash
/usr/bin/find
find version 4.8.0
```

Find is typically pre-installed on Linux systems. Verify availability and version.

- Find is standard on all Unix-like systems
- Different versions available: GNU find, BSD find
- GNU find has more options
- BSD find is on macOS by default

#### Install find on different systems

```bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y findutils

# CentOS/RHEL
sudo yum install -y findutils

# Alpine Linux
apk add findutils

# Arch Linux
sudo pacman -S findutils

# macOS (usually pre-installed)
brew install findutils  # Installs GNU find as gfind
```

_exec_
```bash
find /usr/bin -name "find" -o -name "gfind"
```

_output_
```bash
/usr/bin/find
```

Find is available on all standard Linux systems and macOS, usually pre-installed.

- Findutils package provides GNU find
- macOS comes with BSD find by default
- Install GNU find (gfind) on macOS for compatibility
- Always available on modern Linux distributions

**Best practices:**

- Verify find is available before writing scripts
- Use absolute paths to find command in scripts
- Test on target system if compatibility is needed

**Common errors:**

- **find: command not found**: Install findutils package using system package manager

## Basic Search

Simple file searching by name and basic patterns

### Simple Name Search

Basic file searching by name patterns

**Keywords:** search, name, -name, pattern, file

#### Search for files by exact name

```bash
# Find files by exact name
find . -name "filename.txt"

# Search in specific directory
find /home -name "*.log"

# Search entire filesystem
find / -name "config.ini"

# Multiple directories
find /etc /var -name "*.conf"
```

_exec_
```bash
find /tmp -name "*.tmp" 2>/dev/null | head -3
```

_output_
```bash
/tmp/file1.tmp
/tmp/cache/file2.tmp
/tmp/sessions/file3.tmp
```

Find searches recursively from the specified path for files matching the name pattern.

- Pattern matching uses shell-style wildcards
- * matches any characters in a filename
- matches single character:
- [ ] matches character ranges
- Search is recursive through all subdirectories

#### Name search with wildcards

```bash
# Find all Python files
find . -name "*.py"

# Find by prefix
find . -name "test_*"

# Find by suffix
find . -name "*.backup"

# Complex patterns
find . -name "*[0-9].txt"  # filenames with digits
```

_exec_
```bash
find /home -maxdepth 2 -name "*.md" 2>/dev/null | head -5
```

_output_
```bash
/home/user/README.md
/home/user/Documents/guide.md
/home/user/Downloads/tutorial.md
```

Wildcard patterns provide flexible name matching for common file extensions and naming conventions.

- * matches zero or more characters
- matches exactly one character:
- Patterns are case-sensitive
- Use quotes to prevent shell expansion

**Best practices:**

- Use quotes around patterns to prevent shell expansion
- Use -maxdepth to limit search depth for performance
- Use -type f to search only files (not directories)

**Common errors:**

- **No results found**: Verify pattern is correct and path is accessible

### Case-Insensitive Search

Search for files ignoring case sensitivity

**Keywords:** case, insensitive, -iname, ignore, case

#### Case-insensitive file name search

```bash
# -iname flag for case-insensitive matching
find . -iname "README.txt"

# Matches: readme.txt, README.TXT, ReadMe.txt, etc.
find . -iname "*.LOG"

# Case-insensitive wildcard patterns
find /var -iname "*.pdf"
```

_exec_
```bash
find /home -maxdepth 2 -iname "*.LOG" 2>/dev/null
```

_output_
```bash
/home/user/app.log
/home/user/system/ERROR.LOG
```

The -iname flag performs case-insensitive filename matching, useful when unsure of case.

- -iname is case-insensitive version of -name
- Matches regardless of upper/lowercase
- Combines with wildcards for flexible searching
- Slower than -name (case-sensitive)

#### Mixed case pattern matching

```bash
# Search for backup files regardless of case
find . -iname "*.backup"  # .backup, .BACKUP, .Backup

# Configuration files with various cases
find /etc -iname "*.conf"

# Executable scripts (any case)
find . -iname "*install*"
```

_exec_
```bash
find /tmp -maxdepth 1 -iname "test*" 2>/dev/null | head -5
```

_output_
```bash
/tmp/test_file.txt
/tmp/TEST_data
/tmp/Test_logs.txt
```

Case-insensitive searching helps find files when exact case is unknown.

- Useful for cross-platform searches
- Handles case variations in naming
- Works with all wildcard patterns

**Best practices:**

- Use -iname when case is uncertain
- Combine with -type to filter results
- Use -maxdepth to improve performance

**Common errors:**

- **iname: No such option**: Use -iname with newer find versions; older BSD find may need different approach

### Path Matching

Search by full path or path patterns

**Keywords:** path, -path, directory, location, route

#### Search by full path pattern

```bash
# -path for full path matching
find . -path "*node_modules*"

# Match specific directory structure
find . -path "*/src/components/*.js"

# Exclude patterns with -not
find . -path "*node_modules" -prune -o -name "*.js" -print

# Case-insensitive path matching
find . -ipath "*/downloads/*"
```

_exec_
```bash
find /home -maxdepth 3 -path "*Document*" 2>/dev/null
```

_output_
```bash
/home/user/Documents
/home/user/Documents/files
```

-path matches the entire path from start, useful for excluding directories or matching nested structures.

- -path matches from start of path being tested
- * matches path separators (unlike -name)
- -ipath is case-insensitive version
- Use -prune to skip directories efficiently

#### Path matching with directory pruning

```bash
# Find JavaScript files, skip node_modules
find . -name "node_modules" -prune -o -name "*.js" -print

# Exclude multiple directories
find . \( -path "*/node_modules" -o -path "*/.git" \) -prune -o -name "*.ts" -print

# Find test files, exclude temp directories
find . -path "*/temp" -prune -o -name "*test*" -print
```

_exec_
```bash
find /home -maxdepth 3 -name ".git" -prune -o -type f -name "*.py" -print 2>/dev/null | head -3
```

_output_
```bash
/home/user/script.py
/home/user/projects/tool.py
/home/user/projects/utils.py
```

Combining -prune with -o (or) and -print efficiently skips directories while finding matching files.

- -prune skips entire directory without descending
- More efficient than grep/filter after find
- Use with logical operators for complex patterns

**Best practices:**

- Use -prune to exclude heavy directories like node_modules
- Test path patterns on sample directory first
- Use quotes to prevent shell expansion of path characters

**Common errors:**

- **Unexpected operator or missing operand**: Properly quote path patterns and use parentheses for grouping

### Type Matching

Search by file type (regular files, directories, symlinks, etc.)

**Keywords:** type, -type, file, directory, symlink

#### Search by file type

```bash
# -type flag specifies file type
# f = regular file
# d = directory
# l = symbolic link
# c = character device
# b = block device
# p = named pipe
# s = socket

find . -type f       # regular files only
find . -type d       # directories only
find . -type l       # symbolic links
find /dev -type c    # character devices
```

_exec_
```bash
find /home -maxdepth 2 -type d 2>/dev/null | head -5
```

_output_
```bash
/home
/home/user
/home/user/Documents
/home/user/Downloads
/home/user/Desktop
```

-type d filters to show only directories, excluding regular files and other types.

- f for regular files is most common type
- d for directories, l for symlinks
- Device types (c, b) typically in /dev
- Type matching improves search efficiency

#### Combining type with name search

```bash
# Find Python files (regular files only)
find . -type f -name "*.py"

# Find directories matching pattern
find . -type d -name "*test*"

# Find symlinks to files
find . -type l -name "*.txt"

# Find broken symlinks (point to nothing)
find . -type l ! -exec test -e {} \;
```

_exec_
```bash
find /home -maxdepth 2 -type f -name "*.md" 2>/dev/null | head -3
```

_output_
```bash
/home/user/README.md
/home/user/Documents/guide.md
/home/user/Downloads/tutorial.md
```

Combining -type f with -name "*.md" finds only regular markdown files, excluding directories.

- Always use -type f with name patterns for efficiency
- Reduces false positives from directories
- Works with other criteria like size and time

**Best practices:**

- Use -type f with name patterns for accuracy
- Combine -type with other filters for efficiency
- Use -type d to find only directories

**Common errors:**

- **Wrong file type matched**: Verify -type flag is included in command

## File Size & Type

Filter files by size and specific type tests

### Size Filtering

Search files by size with various units and comparisons

**Keywords:** size, -size, bytes, kilobytes, filter

#### Find files by size

```bash
# -size flag for file size filtering
# c = bytes
# k = kilobytes (1024 bytes)
# M = megabytes (1024 KB)
# G = gigabytes (1024 MB)

find . -size +1M        # larger than 1MB
find . -size -1M        # smaller than 1MB
find . -size 100c       # exactly 100 bytes
find . -size 5k         # exactly 5 kilobytes
```

_exec_
```bash
find /home -maxdepth 2 -type f -size +10M 2>/dev/null
```

_output_
```bash
/home/user/Downloads/large_video.mp4
/home/user/backup/archive.tar.gz
```

-size finds files larger than 10MB, useful for identifying large files consuming disk space.

- + means larger than, - means smaller than
- No prefix means exactly that size
- Units: c (bytes), k (1024 bytes), M (1024 KB), G (1024 MB)
- Size is rounded, so +1M includes files > 1,048,576 bytes

#### Find disk space hogs

```bash
# Find large files for cleanup
find . -type f -size +100M

# Find files exactly 1MB
find . -type f -size 1M

# Range of sizes
find . -type f -size +1M -size -100M

# Empty files (special case)
find . -type f -size 0
```

_exec_
```bash
find /tmp -type f -size +1M 2>/dev/null
```

_output_
```bash
/tmp/cache/large.dat
```

Combining size criteria finds files in specific size ranges for storage analysis.

- Size filtering helps manage disk usage
- Use + and - to define ranges
- Combine with -type f for accuracy

**Best practices:**

- Use size filtering to identify disk space hogs
- Combine multiple size criteria for ranges
- Use with deletion carefully (-delete flag)

**Common errors:**

- **Size units not recognized**: Use valid units: c, k, M, G only

### File Type Tests

Test file type with specific attributes

**Keywords:** type, test, -type, device, socket

#### Search by specific file types

```bash
# Find symbolic links
find . -type l

# Find character devices
find /dev -type c

# Find block devices
find /dev -type b

# Find named pipes (FIFOs)
find /tmp -type p

# Find sockets
find /run -type s
```

_exec_
```bash
find /dev -maxdepth 1 -type c 2>/dev/null | head -3
```

_output_
```bash
/dev/null
/dev/zero
/dev/random
```

Find searches for character devices in /dev, which are special file types representing hardware.

- l = symlinks, c = character devices, b = block devices
- Useful for system administration tasks
- Device files in /dev controlled by kernel

#### Advanced type combinations

```bash
# Find broken symlinks
find . -type l -xtype l

# Find symlinks to directories
find . -type l

# Find all non-regular files
find . ! -type f

# Find files and directories (not devices)
find . \( -type f -o -type d \)
```

_exec_
```bash
find /home -maxdepth 3 -type l 2>/dev/null | head -3
```

_output_
```bash
/home/user/.oh-my-zsh -> /usr/share/oh-my-zsh
/home/user/.config/app/plugins -> ../../../opt/plugins
```

Finding symbolic links helps identify shortcuts and dependencies in the filesystem.

- -xtype tests the type of file link points to
- operator negates conditions
- Parentheses group conditions with -o (or)

**Best practices:**

- Use -type for efficiency before other tests
- Combine type tests with other criteria
- Test symlinks with -type l -xtype l

**Common errors:**

- **File not found for symlink**: Use -type l to find symlinks, not -xtype for broken links

### Empty Files

Search for empty files and directories

**Keywords:** empty, size, -size, zero, blank

#### Find empty files and directories

```bash
# Find empty regular files
find . -type f -size 0

# Find empty directories
find . -type d -empty

# Find and delete empty files
find . -type f -size 0 -delete

# Find empty files with timestamp info
find . -type f -size 0 -ls
```

_exec_
```bash
find /tmp -maxdepth 2 -type f -size 0 2>/dev/null | head -3
```

_output_
```bash
/tmp/placeholder.txt
/tmp/cache/empty.log
```

Find locates empty files with -size 0 or using -empty test flag.

- -size 0 finds files with zero bytes
- -empty tests both empty files and directories
- Useful for cleanup operations
- Be careful with -delete flag

#### Cleanup empty files

```bash
# Count empty files
find . -type f -size 0 | wc -l

# Remove empty files and directories
find . -type f -empty -delete
find . -type d -empty -delete

# Safe delete with confirmation
find . -type f -size 0 -exec rm -i {} \;
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -empty 2>/dev/null | wc -l
```

_output_
```bash
2
```

Combining -empty with -delete removes empty files, useful for storage cleanup.

- -delete removes found items permanently
- -exec with -i provides confirmation before delete
- Test before deleting on important filesystems

**Best practices:**

- Use -ls before -delete to verify results
- Test find command without -delete first
- Use -exec rm -i for safer deletion

**Common errors:**

- **Deleted wrong files**: Always preview with find first, verify criteria before using -delete

## Time-Based Search

Search files by modification, access, and change times

### Modification Time

Search files by modification time

**Keywords:** mtime, modified, time, days, -mtime

#### Find files by modification time

```bash
# -mtime flag: modification time in days
# n = exactly n days old
# +n = more than n days old
# -n = less than n days old

find . -mtime 0       # modified today
find . -mtime 1       # modified exactly 1 day ago
find . -mtime +30     # modified more than 30 days ago
find . -mtime -7      # modified in last 7 days
```

_exec_
```bash
find /var/log -maxdepth 1 -type f -mtime +30 2>/dev/null
```

_output_
```bash
/var/log/syslog.1
/var/log/secure.log
```

Find locates files modified more than 30 days ago, useful for archiving old logs.

- mtime is modification time in complete days
- +30 means more than 30 days (older)
- -7 means less than 7 days (newer)
- 0 means today (last 24 hours)

#### Archive old files

```bash
# Find and archive logs older than 90 days
find /var/log -type f -mtime +90 | tar czf archive.tar.gz --files-from=-

# Find old backup files and delete
find /backups -type f -name "*.bak" -mtime +365 -delete

# Find recently modified files
find . -type f -mtime -1  # last 24 hours
```

_exec_
```bash
find /tmp -maxdepth 2 -type f -mtime 0 2>/dev/null | head -3
```

_output_
```bash
/tmp/session-20250228.dat
/tmp/cache/update.log
```

Find can identify recently modified files for backup or analysis purposes.

- -mtime 0 means modified since midnight
- Use with -mmin for minute-level precision
- Useful for automated cleanup scripts

**Best practices:**

- Use -mtime for day-level time filtering
- Combine with -type f for regular files only
- Test criteria before using -delete

**Common errors:**

- **Wrong time period matched**: Remember +n (older), -n (newer), 0 (today)

### Access Time

Search files by access time (when file was read)

**Keywords:** atime, access, -atime, read, time

#### Find files by access time

```bash
# -atime flag: access time (last read)
find . -atime 0        # accessed today
find . -atime +30      # accessed more than 30 days ago
find . -atime -7       # accessed in last 7 days

# Find files never accessed since modification
find . -amin -10       # accessed in last 10 minutes
```

_exec_
```bash
find /home -maxdepth 2 -type f -atime +180 2>/dev/null | head -3
```

_output_
```bash
/home/user/.cache/old_cache.db
/home/user/Documents/archive.zip
```

Find files not accessed for more than 6 months, candidates for archiving.

- atime = access time (when file was read)
- Measured in days with -atime
- Use -amin for minute precision
- Some filesystems disable atime for performance

#### Find unused files for cleanup

```bash
# Find files not accessed in a year
find . -type f -atime +365

# Find large files not accessed recently
find . -type f -size +1M -atime +90

# List files with access time info
find . -type f -atime +30 -ls
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -atime +7 2>/dev/null | head -2
```

_output_
```bash
/tmp/download.tmp
```

Finding rarely accessed files helps identify candidates for removal to free disk space.

- atime tracking may be disabled on some systems
- Combine with size for storage analysis
- Use with -ls to see file details

**Best practices:**

- Check if filesystem uses atime (may be disabled for performance)
- Combine atime with mtime for better analysis
- Use -amin for minute-level access time searches

**Common errors:**

- **atime not updating**: Some filesystems have noatime option; check mount options with mount command

### Change Time

Search files by change time (metadata changes)

**Keywords:** ctime, change, -ctime, metadata, inode

#### Find files by change time

```bash
# -ctime flag: change time (inode changes)
# Changed when: content modified, permissions changed, owner changed
find . -ctime 0        # changed today
find . -ctime +7       # changed more than 7 days ago
find . -ctime -1       # changed in last 24 hours

# Find files with recent permission changes
find . -ctime -1 ! -mtime -1
```

_exec_
```bash
find /etc -maxdepth 1 -type f -ctime -1 2>/dev/null | head -3
```

_output_
```bash
/etc/shadow
/etc/passwd
```

Find system configuration files changed in the last 24 hours (permissions or ownership changes).

- ctime = change time (metadata like permissions, ownership)
- Different from mtime (content modification)
- Updated when inode information changes
- Useful for detecting permission changes

#### Monitor configuration changes

```bash
# Find config files changed recently
find /etc -name "*.conf" -ctime -1

# Find permission changes (ctime but not mtime change)
find . -ctime -1 ! -mtime -1

# System changes detection
find /etc -type f -ctime -7
```

_exec_
```bash
find /home -maxdepth 2 -type f -ctime -1 2>/dev/null | head -3
```

_output_
```bash
/home/user/.bash_history
/home/user/.cache/recent.db
```

Find files with recent timestamp or permission modifications for monitoring system changes.

- Useful for security monitoring
- Detects permission/ownership changes
- Different from mtime for pure content changes

**Best practices:**

- Use ctime to detect permission and ownership changes
- Combine ctime and mtime for comprehensive analysis
- Monitor system files for unauthorized changes

**Common errors:**

- **Confusing ctime with mtime**: ctime=metadata changes, mtime=content changes

### Minute-Based Searches

Search files by minute-level time precision

**Keywords:** minute, -mmin, -amin, -cmin, time

#### Find files by minute-level time

```bash
# -mmin, -amin, -cmin for minute precision
# Same operators as day versions

find . -mmin -5        # modified in last 5 minutes
find . -mmin 0         # modified in current minute
find . -amin +60       # not accessed in 60+ minutes
find . -cmin -10       # changed in last 10 minutes
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -mmin -10 2>/dev/null | head -3
```

_output_
```bash
/tmp/session.log
/tmp/cache/update.dat
```

Find files modified in the last 10 minutes for monitoring recent activity.

- -mmin uses minutes instead of days
- Same operators: +n (older), -n (newer)
- -amin for access time in minutes
- -cmin for change time in minutes

#### Real-time file monitoring

```bash
# Find files modified in last minute
find /var/log -type f -mmin -1

# Find recently created files
find . -type f -cmin -2

# Monitor temp directory
watch -n 60 'find /tmp -type f -mmin -5'

# Activity monitoring script
while true; do find . -type f -mmin -1; sleep 60; done
```

_exec_
```bash
find /var -maxdepth 1 -type f -mmin -30 2>/dev/null | head -3
```

_output_
```bash
/var/adm/sulog
/var/syslog/current
```

Minute-level searches enable real-time monitoring of file activity.

- Useful for logs and activity monitoring
- Can be used in watch loops
- Helpful for debugging and troubleshooting

**Best practices:**

- Use -mmin for recent file monitoring
- Combine with -ls for detailed output
- Use in watch loops for continuous monitoring

**Common errors:**

- **Too many results with -mmin**: Use smaller time windows and filters

## Permissions & Ownership

Search files by permissions and ownership

### Permission Tests

Search files by permission settings

**Keywords:** permissions, -perm, mode, chmod, access

#### Find files by permission

```bash
# -perm flag for permission matching
find . -perm 644       # exactly 644 (rw-r--r--)
find . -perm -644      # has at least these permissions
find . -perm /644      # matches any of these bits
find . -perm u+x       # user executable
find . -perm -u=rwx    # has all permissions for user
```

_exec_
```bash
find /home -maxdepth 2 -type f -perm 644 2>/dev/null | head -3
```

_output_
```bash
/home/user/.bashrc
/home/user/file.txt
/home/user/Documents/readme.md
```

Find files with exactly 644 permissions (rw-r--r--), common for regular files.

- -perm mode matches exactly that permission mode
- -perm -mode matches files with at least those permissions
- -perm /mode matches any of the specified bits
- Modes can be octal (644) or symbolic (a+r)

#### Find dangerous permissions

```bash
# Find world-writable files
find . -perm -o=w

# Find SUID files
find / -perm -u+s

# Find SGID files
find / -perm -g+s

# Find sticky bit files
find / -perm -u+t

# Find world-readable sensitive files
find /etc -type f -perm -o=r
```

_exec_
```bash
find /usr -maxdepth 2 -type f -perm -u+s 2>/dev/null | head -3
```

_output_
```bash
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/chfn
```

Find SUID files which run with owner privileges, security-critical to monitor.

- -o=w finds world-writable files (security risk)
- -u+s finds SUID bits (runs as owner)
- -g+s finds SGID bits (runs as group)
- u+t finds sticky bit (often on /tmp)

**Best practices:**

- Regularly audit SUID/SGID files
- Prevent world-writable files in sensitive areas
- Understand permission implications

**Common errors:**

- **Permission matching not working**: Use correct format: -perm exactly, -perm -at least, -perm /any bit

### User/Group Ownership

Search files by user or group ownership

**Keywords:** user, group, -user, -group, owner

#### Find files by user ownership

```bash
# -user flag for user ownership
find . -user root       # owned by root
find . -user nobody     # owned by nobody user
find /home -user $USER  # files owned by current user
find . ! -user root     # NOT owned by root

# Find files by numeric UID
find . -uid 1000        # files with UID 1000
```

_exec_
```bash
find /home -maxdepth 2 -user root 2>/dev/null | head -3
```

_output_
```bash
/home/shared/admin-config
/home/shared/system-backup
```

Find files owned by root in user directories, potentially security issues.

- -user looks up username from /etc/passwd
- -uid uses numeric user ID directly
- -user negates the condition
- $USER expands to current username

#### Find files by group ownership

```bash
# -group flag for group ownership
find . -group admin     # group-owned by admin
find . -group staff     # group staff
find /tmp -group root   # temp files owned by root
find . ! -group wheel   # NOT group wheel

# Find files by numeric GID
find . -gid 1001        # files with GID 1001
```

_exec_
```bash
find /home -maxdepth 1 -type d -group users 2>/dev/null
```

_output_
```bash
/home/user1
/home/user2
```

Find directories owned by the 'users' group.

- -group looks up group name from /etc/group
- -gid uses numeric group ID directly
- -group negates the condition

**Best practices:**

- Use -user to find owned files for backup
- Use -group for group-based permission audits
- Combine with -perm for comprehensive security review

**Common errors:**

- **User/group name not found**: Verify username/group exists in /etc/passwd or /etc/group

### Executable/Readable/Writable Tests

Search files by specific permission tests

**Keywords:** executable, readable, writable, -executable, -readable, -writable

#### Find executable files

```bash
# -executable tests if file is executable by current user
find . -type f -executable

# Executable scripts
find . -type f -executable -name "*.sh"

# Non-executable regular files
find . -type f ! -executable

# Find executable in PATH
find $PATH -type f -executable -name "find"
```

_exec_
```bash
find /usr/bin -maxdepth 1 -type f -executable -name "ls*" 2>/dev/null
```

_output_
```bash
/usr/bin/ls
```

Find executable files matching pattern - shell commands like ls.

- -executable tests if current user can execute
- Works with -name for specific executable search
- -executable finds non-executable files
- Useful for security audits

#### Find readable and writable files

```bash
# -readable tests if file is readable by current user
find . -type f -readable

# -writable tests if file is writable by current user
find . -type f -writable

# Files readable but not writable
find . -type f -readable ! -writable

# Writable-only files (unusual)
find . -type f ! -readable -writable
```

_exec_
```bash
find /home -maxdepth 2 -type f -readable ! -writable 2>/dev/null | head -3
```

_output_
```bash
/home/user/important.txt
/home/user/Documents/archive
```

Find read-only files which are readable but not writable by current user.

- -readable tests read permission for current user
- -writable tests write permission
- Respects user's actual permissions
- Useful for access verification

**Best practices:**

- Use -executable to find scripts and binaries
- Use -readable/-writable for access checks
- Combine with -user/-group for ownership verification

**Common errors:**

- **Permissions show different from -perm**: -executable/-readable/-writable test actual user access, -perm tests file mode

## Advanced Operations

Complex operations combining multiple criteria

### Logical Operators

Combine multiple search criteria using logical operators

**Keywords:** logical, operators, -and, -or, -not

#### Combine conditions with AND and OR

```bash
# -and (implicit between conditions)
find . -type f -name "*.py"  # type AND name

# -o for OR operator
find . \( -name "*.py" -o -name "*.js" \)

# ! for NOT operator
find . ! -name "*.tmp"

# Complex combinations
find . -type f \( -name "*.log" -o -name "*.txt" \) -size +1M
```

_exec_
```bash
find /home -maxdepth 2 -type f \( -name "*.py" -o -name "*.js" \) 2>/dev/null | head -3
```

_output_
```bash
/home/user/script.py
/home/user/app.js
/home/user/projects/utils.py
```

Find files with either .py or .js extension using OR operator with parentheses.

- Multiple conditions are AND by default (implicit)
- -o provides OR logic
- ! provides NOT logic
- Parentheses group conditions
- Escape parentheses in shell: \( \)

#### Complex logical expressions

```bash
# Find large files modified today OR accessed recently
find . -size +10M \( -mtime 0 -o -atime -1 \)

# Find Python files not in test directory
find . -name "*.py" ! -path "*/test*"

# Find recently modified OR changed files
find . \( -mtime -1 -o -ctime -1 \) -type f

# Complex: large old files not backed up
find . -size +100M -mtime +90 ! -name "*.backup"
```

_exec_
```bash
find /home -maxdepth 2 -type f \( -name "*.pdf" -o -name "*.doc" \) -size +1M 2>/dev/null | head -3
```

_output_
```bash
/home/user/Documents/thesis.pdf
/home/user/Downloads/manual.pdf
```

Find large document files combining OR logic with size filtering.

- Group with parentheses for complex expressions
- AND binds tighter than OR in traditional logic
- Parentheses ensure proper evaluation order

**Best practices:**

- Use parentheses to clarify expression intent
- Test complex expressions on sample data first
- Use path exclusions early for performance

**Common errors:**

- **Unexpected operator**: Escape parentheses with backslash: \\( \\)

### Directory Pruning

Skip directories to improve search performance

**Keywords:** prune, skip, -prune, directory, exclude

#### Prune directories to skip recursion

```bash
# -prune skips directory without descending
find . -name "node_modules" -prune -o -name "*.js" -print

# Skip multiple directories
find . \( -path "*/node_modules" -o -path "*/.git" \) -prune -o -type f -print

# Skip .git and .venv
find . -name ".git" -prune -o -name ".venv" -prune -o -type f -print

# Common excluded directories
find . -path "*/.git" -prune -o -path "*/node_modules" -prune -o -type f -print
```

_exec_
```bash
find /home -maxdepth 2 -name ".cache" -prune -o -type f -name "*.md" -print 2>/dev/null | head -3
```

_output_
```bash
/home/user/README.md
/home/user/Projects/guide.md
```

Prune .cache directory to skip hidden cache, finding only markdown files.

- -prune stops descending into matched directories
- Much faster than searching and filtering
- Used in "path -prune -o action -print" pattern
- -o (or) follows -prune for alternative action

#### Efficient recursive search with prune

```bash
# Find source files, skip build and cache
find . -type d \( -name "build" -o -name "dist" -o -name ".cache" \) -prune -o -type f -name "*.src" -print

# Search for config files, skip system directories
find /home -type d -name ".config" -prune -o -name "config.json" -print

# Find all files, avoid large directories
find . \( -name "node_modules" -o -name ".git" -o -name "venv" \) -prune -o -type f -print
```

_exec_
```bash
find /tmp -maxdepth 3 \( -name ".git" -o -name ".cache" \) -prune -o -type f -print 2>/dev/null | head -3
```

_output_
```bash
/tmp/session.log
/tmp/data/config.json
```

Combined pruning of multiple directories for efficient searching while excluding unneeded paths.

- Parentheses group multiple -name conditions
- -o separates multiple directories to prune
- Results in much faster searches
- Essential for projects with large dependencies

**Best practices:**

- Always prune node_modules in JavaScript projects
- Prune .git, .venv, build directories
- Test with -prune to verify correct directories are skipped

**Common errors:**

- **Still searching in excluded directories**: Ensure -prune is in correct logical position before the action

### Regular Expressions

Use regex patterns for matching in find

**Keywords:** regex, expression, -regex, -iregex, pattern

#### Find with regular expressions

```bash
# -regex for full path regex matching
find . -regex ".*\.py$"          # Python files
find . -regex ".*test.*\.js$"    # test JavaScript files
find . -regex ".*/src/.*\.ts$"   # TypeScript in src/

# -iregex for case-insensitive
find . -iregex ".*\.(log|txt)$"  # .log or .txt files (case-insensitive)

# Regex with character classes
find . -regex ".*[0-9]\{4\}\.txt$"  # files with 4 digits before .txt
```

_exec_
```bash
find /home -maxdepth 3 -regex ".*\.pdf$" 2>/dev/null | head -3
```

_output_
```bash
/home/user/Documents/report.pdf
/home/user/manual.pdf
```

Find PDF files using regex pattern matching full path.

- -regex matches full path (not just filename)
- Pattern is extended regex by default
- .* matches any characters to root
- $ anchors match path end
- Slower than -name but more flexible

#### Complex regex patterns

```bash
# Find versioned files
find . -regex ".*v[0-9]+\.[0-9]+\.txt$"

# Find config files in specific structure
find . -regex ".*/config/[^/]*\.json$"

# Find date-named files
find . -regex ".*[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.*"

# Find non-dotfiles
find . -regex ".*/[^.][^/]*$"
```

_exec_
```bash
find /var -maxdepth 2 -regex ".*\.(log|tmp)$" 2>/dev/null | head -3
```

_output_
```bash
/var/log/syslog.log
/var/tmp/session.tmp
```

Find log and temp files using regex pattern with alternation.

- Regex provides powerful pattern matching
- Performance cost vs simple -name
- Extended regex is default (no need to escape special chars in [])

**Best practices:**

- Use -name for simple patterns (faster)
- Use -regex for complex patterns
- Anchor patterns with ^ and $ where needed

**Common errors:**

- **Regex not matching expected files**: Remember -regex matches full path from current directory

### Execution with Files

Execute commands on found files safely

**Keywords:** execution, -exec, -execdir, xargs, command

#### Execute commands with -exec

```bash
# -exec runs command on each found file
# {} placeholder replaced with filename
# ; terminates command (escape with \;)

find . -name "*.log" -exec rm {} \;
find . -type f -exec chmod 644 {} \;
find . -name "*.py" -exec python3 {} \;

# -exec with output
find . -type f -exec wc -l {} \;
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -name "*.txt" -exec ls -lh {} \; 2>/dev/null
```

_output_
```bash
-rw-r--r-- 1 user user 12K /tmp/file1.txt
-rw-r--r-- 1 user user 5.2K /tmp/file2.txt
```

Execute ls command on each found .txt file showing detailed information.

- {} is placeholder for found filename
- \\; terminates the command
- Spawns new process for each file
- Can be slow with many files

#### Safe and efficient execution

```bash
# -exec with + instead of ; (more efficient)
find . -type f -exec grep -l "TODO" {} +

# -execdir runs in file's directory
find . -type f -name "*.bak" -execdir rm {} \;

# Interactive prompt with -ok
find . -type f -name "*.tmp" -ok rm {} \;

# Use xargs for better performance
find . -type f -print0 | xargs -0 rm
```

_exec_
```bash
find /home -maxdepth 2 -type f -name "*.md" -exec wc -l {} + 2>/dev/null | tail -1
```

_output_
```bash
42 total
```

Use + instead of ; to pass multiple files to command for efficiency.

- + batches files into single command call (more efficient)
- -execdir changes to file directory before executing
- -ok prompts before each execution
- -print0 with xargs handles spaces in filenames

#### Common exec patterns

```bash
# Remove old files
find . -type f -mtime +90 -exec rm -f {} \;

# Change permissions
find . -type f -exec chmod 644 {} +
find . -type d -exec chmod 755 {} +

# Show file information
find . -type f -name "*.log" -exec ls -lh {} \;

# Compress old logs
find /var/log -type f -mtime +30 -exec gzip {} \;
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -exec base64 {} \\; 2>/dev/null | head -2
```

_output_
```bash
ZmlsZSBjb250ZW50IGluIGJhc2U2NAo=
```

Execute base64 encoding on found files.

- Common use: rm, chmod, gzip, grep
- Always test before destructive operations
- Use + for better performance when possible

**Best practices:**

- Always test -exec commands without actual execution first
- Use + instead of \\\; for better performance
- Use -ok for interactive confirmation on important operations

**Common errors:**

- **Command not executing or syntax error**: Verify {} and \\; are present; test quoting

## Output & Actions

Control output format and perform actions on files

### Print Options

Format output from find command

**Keywords:** print, output, -print, -printf, format

#### Format find output

```bash
# Default -print (newline separated)
find . -name "*.py"      # same as: find . -name "*.py" -print

# -print0 for null-terminated (handles spaces)
find . -type f -print0 | xargs -0 ls -la

# -printf for custom formatting
find . -type f -printf "%p %s bytes\n"

# Format options:
# %p = path
# %s = size
# %m = permissions (octal)
# %u = username
# %g = group
# %T = modification time
```

_exec_
```bash
find /home -maxdepth 2 -type f -printf "%f %s\n" 2>/dev/null | head -3
```

_output_
```bash
bashrc 2145
vimrc 5329
config.json 1024
```

Custom printf format showing filename and size in bytes.

- -printf builds custom output format
- %f = filename only, %p = full path
- %s = size, %m = permissions
- %u = user, %g = group
- \\n for newline, \\t for tab

#### Advanced output formatting

```bash
# File info with permissions
find . -type f -printf "%m %u:%g %s %p\n"

# Size in human-readable format
find . -type f -exec ls -lh {} + | awk '{print $9, $5}'

# JSON-like output
find . -type f -printf "{\\"file\\": \\"%p\\", \\"size\\": %s}\n"

# List with timestamps
find . -type f -printf "%TY-%Tm-%Td %p\n"
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -printf "%u %s %f\n" 2>/dev/null | head -3
```

_output_
```bash
root 2048 config.tmp
user 1024 session.dat
```

Show owner, size, and filename in custom format.

- %T formatter for time (complex)
- %m for octal permissions
- Useful for parsing and post-processing

**Best practices:**

- Use -printf for structured output
- Use -print0 with xargs for filename safety
- Use -ls for quick detailed listing

**Common errors:**

- **Unknown format specifier**: Use valid printf formats: %p, %s, %m, %u, %g, %T

### Deletion Actions

Delete files matching criteria

**Keywords:** delete, removal, -delete, dangerous, cleanup

#### Delete files matching criteria

```bash
# -delete removes found files
# BE CAREFUL - permanent deletion!

find . -type f -name "*.tmp" -delete

# Delete empty files
find . -type f -size 0 -delete

# Delete old files
find /tmp -type f -mtime +30 -delete

# Delete in specific directory
find /tmp -maxdepth 1 -type f -delete
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -name "*.tmp" -delete 2>/dev/null; echo "Deleted"
```

_output_
```bash
Deleted
```

Delete all .tmp files in /tmp directory.

- -delete removes found items permanently
- No confirmation or recovery possible
- Always test command first
- Consider backing up before bulk delete

#### Safe deletion with confirmation

```bash
# Preview before deleting
find . -name "*.log" -mtime +30  # preview first

# Then delete with confirmation
find . -name "*.log" -mtime +30 -ok rm {} \;

# Safe delete with list
find . -type f -size 0 -ls     # list empty files
find . -type f -size 0 -delete # delete them

# Backup before deletion
find . -type f -mtime +365 -exec cp {} {}.backup \;
find . -type f -mtime +365 -delete
```

_exec_
```bash
find /tmp -maxdepth 2 -type f -name "test_*.log" -ls 2>/dev/null | head -1
```

_output_
```bash
2097152  4 -rw-r--r-- 1 user user   2048 Feb 28 10:30 /tmp/test_run.log
```

List files with -ls before deletion for safety verification.

- Always preview with -ls or -printf before -delete
- Use -ok with rm for interactive confirmation
- Keep backups for important deletions

**Best practices:**

- ALWAYS preview with find first before -delete
- Use -ls to verify correct files will be deleted
- Test on safe directory first
- Use -ok rm instead of -delete for confirmation

**Common errors:**

- **Deleted wrong files accidentally**: Always preview with find first, use small examples

### Advanced Exec Commands

Complex command execution patterns

**Keywords:** exec, command, processing, batch, variables

#### Process files with exec commands

```bash
# Run command on each file
find . -type f -name "*.jpg" -exec file {} \;

# Batch process multiple files
find . -name "*.txt" -exec cat {} + > combined.txt

# Get file info
find . -type f -exec stat {} \;

# Process with pipes
find . -type f -exec grep -l "error" {} \;
```

_exec_
```bash
find /home -maxdepth 2 -type f -name "*.md" -exec wc -l {} + 2>/dev/null
```

_output_
```bash
42 /home/user/README.md
15 /home/user/GUIDE.md
57 total
```

Count lines in markdown files combining with + for batching.

- {} is replaced with found filename
- + batches multiple files in single command call
- \\; runs command for each file separately
- Pipe output with $(...)

#### Complex exec workflows

```bash
# Convert image files
find . -name "*.png" -exec convert {} {}.jpg \;

# Validate files before processing
find . -type f -exec sh -c 'head -c 4 "$1" | grep -q "^PDF" && echo "$1"' _ {} \;

# Parallel processing with GNU parallel
find . -name "*.log" | parallel gzip {}

# Backup and delete
find . -type f -mtime +365 -exec mv {} /backup/\; -delete
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -exec file {} \\; 2>/dev/null | head -2
```

_output_
```bash
/tmp/session.log: ASCII text
/tmp/cache.dat: data
```

Identify file types using the 'file' command on found files.

- Complex shell commands can follow -exec
- Use sh -c for complex one-liners
- GNU parallel for parallel processing

**Best practices:**

- Use + for batching when possible (more efficient)
- Escape special characters in complex commands
- Test complex exec patterns in safe directories

**Common errors:**

- **Syntax errors in complex exec commands**: Quote properly and test simple version first

## Practical Examples

Real-world use cases and performance tips

### Real-World Use Cases

Common practical scenarios using find

**Keywords:** backup, cleanup, analysis, monitoring, maintenance

#### Cleanup large old files

```bash
# Find and list large files modified long ago
find /home -type f -size +100M -mtime +90 -exec ls -lh {} \;

# Archive old large files
find /var/log -type f -size +10M -mtime +30 | tar czf archive.tar.gz --files-from=-

# Delete old temp files
find /tmp -type f -mtime +7 -delete

# Cleanup disk space safely
find . -type f \( -name "*.tmp" -o -name "*.bak" -o -name "*.log" \) -delete
```

_exec_
```bash
find /var/log -maxdepth 1 -type f -mtime +30 -exec ls -lh {} \; 2>/dev/null | head -2
```

_output_
```bash
-rw-r--r-- 1 root root 45M Feb 28 12:00 /var/log/syslog.1
-rw-r--r-- 1 root root 23M Feb 28 10:00 /var/log/auth.log
```

Find and list large log files older than 30 days for archiving or deletion.

- Always use -mtime and size together for cleanup
- Backup before making changes
- Use -ls to preview before deletion
- Monitor free space regularly

#### Project maintenance

```bash
# Find source files recursively, skip build
find . -path "./build" -prune -o -path "./dist" -prune -o -type f -name "*.src" -print

# Count lines of code
find . -name "*.py" -exec wc -l {} + | tail -1

# Find files needing update
find . -type f -name "*.js" -mtime +365

# Analyze code patterns
find . -name "*.py" -exec grep -l "TODO" {} \;
```

_exec_
```bash
find /home -maxdepth 3 -name "*.py" -type f -exec wc -l {} + 2>/dev/null | tail -1
```

_output_
```bash
1250 total
```

Count total lines of Python code across project.

- Prune build directories for accuracy
- Use grep to find patterns in code
- Monitor code metrics over time

#### Security and permissions audit

```bash
# Find SUID files (security risk)
find / -type f -perm -u+s 2>/dev/null

# Find world-writable files
find . -type f -perm -o+w

# Find files with unusual permissions
find . -type f ! -perm 644

# Find recently modified system files
find /etc -type f -mtime -1

# Find files with no owner
find . -nouser
```

_exec_
```bash
find /home -maxdepth 2 -type f -perm /go+w 2>/dev/null | head -2
```

_output_
```bash
/home/user/shared_file.txt
```

Find files with group or other write permissions (potential security issue).

- Audit SUID/SGID files regularly
- Check for world-writable files
- Monitor system file changes

#### Backup and synchronization

```bash
# Find recent files for backup
find . -type f -mtime -1 | tar czf backup_today.tar.gz --files-from=-

# Identify changed files
find . -mtime -7 -o -ctime -7

# Mirror directory with permissions
find . -type f | cpio -p -d -v /backup/

# Create modification list for sync
find . -type f -printf "%T@ %p\n" | sort -n
```

_exec_
```bash
find /home -maxdepth 2 -type f -mtime -1 2>/dev/null | wc -l
```

_output_
```bash
12
```

Count files modified in last day for backup purposes.

- Use tar with --files-from for safe backup
- cpio alternative for file copying
- Sort by modification time for analysis

**Best practices:**

- Always test find command before destructive operations
- Use -mtime and size for cleanup operations
- Monitor important directories regularly
- Keep backups before bulk changes

**Common errors:**

- **Backup failed or files missed**: Preview find output first, verify file count

### Performance Optimization

Tips for efficient find usage on large filesystems

**Keywords:** performance, optimization, speed, large, filesystem

#### Optimize find performance

```bash
# Use -maxdepth to limit recursion depth
find . -maxdepth 3 -type f -name "*.py"

# Type first (most selective)
find . -type f -name "*.log"  # better
find . -name "*.log" -type f  # slower

# Prune large directories early
find . -path "*/node_modules" -prune -o -type f -print

# Suppress error messages to speed up
find . -name "*.js" 2>/dev/null
```

_exec_
```bash
find /home -maxdepth 2 -type f 2>/dev/null | wc -l
```

_output_
```bash
342
```

Count files with limited depth and Error suppression for faster execution.

- -maxdepth reduces directory traversal
- Type filter is very selective
- -prune skips entire directories efficiently
- Redirect stderr (2>/dev/null) to hide permission errors

#### Filesystem-specific optimizations

```bash
# Find with NFS filesystem (use -noleaf)
find /mnt/nfs -noleaf -type f -name "*.txt"

# Find local filesystem (use -xdev to skip other filesystems)
find / -xdev -type f -name "config"

# Parallel find on large directories
find . -type d | parallel find {} -maxdepth 1 -type f

# Use locate for filename-only searches (fast)
locate "*.py"  # much faster than find . -name "*.py"
```

_exec_
```bash
find /etc -xdev -type f -name "*.conf" 2>/dev/null | wc -l
```

_output_
```bash
23
```

Use -xdev to stay on same filesystem when searching /etc.

- -noleaf for NFS mounted directories
- -xdev prevents crossing filesystem boundaries
- locate database much faster for name-only searches
- GNU parallel can distribute work across cores

#### Batch operations efficiently

```bash
# Batch with + instead of separate calls with \;
find . -type f -exec chmod 644 {} +    # fast: 1 process/call
find . -type f -exec chmod 644 {} \;   # slow: 1 process/file

# Use xargs with parallel execution
find . -type f -print0 | xargs -0 -P 4 rm

# Combine sort and processing
find . -type f -printf "%s %p\n" | sort -rn | head -10

# Process in batches
find . -type f | head -100 | xargs tar czf batch1.tar.gz
```

_exec_
```bash
find /tmp -maxdepth 1 -type f -exec ls -1 {} + 2>/dev/null | head -3
```

_output_
```bash
/tmp/file1.txt
/tmp/file2.log
/tmp/file3.tmp
```

Use + to batch files into one command for better performance.

- + batches multiple files (one process/batch)
- \\; calls process for each file (slow)
- xargs -P uses multiple parallel processes
- Sort by size for analysis with -printf

**Best practices:**

- Always use -maxdepth to limit search depth
- Prune heavy directories like node_modules
- Use -xdev to stay on one filesystem
- Use + instead of \\; for batch operations

**Common errors:**

- **Find is slow on large directories**: Use -maxdepth, -prune, and + batching
