Introduction / Why This Is Useful
File searching in Linux is one of the most frequent tasks for a system administrator, developer, and regular user. Instead of a graphical browser, you use a powerful command line that allows you to find files by any criterion: name, size, date, content, or access permissions. This guide will teach you how to effectively use the find, locate, and fd utilities to solve everyday tasks, from a simple "where's my config?" to finding gigabyte-sized files filling up the disk.
After completing this guide, you will be able to:
- Quickly find files by name using patterns.
- Search for files by size and date to free up space.
- Locate executable files or files with specific permissions.
- Choose the right tool (
find,locate,fd) for each situation.
Requirements / Preparation
- Access to a Linux terminal (any distribution: Ubuntu, CentOS, Arch, Fedora, etc.).
- Basic navigation knowledge (
cd,ls). - Read permissions on the directories you will be searching. For system directories (
/etc,/var),sudomay be required. - For the
fdutility (optional but recommended):
After installation, the command may be called# Ubuntu/Debian sudo apt update && sudo apt install fd-find # Fedora sudo dnf install fd-find # Arch Linux sudo pacman -S fd # macOS (brew) brew install fdfdfind(in Debian/Ubuntu) orfd.
Step-by-Step Instructions
Step 1: Basic find Command Syntax
The find command has a universal syntax:
find [search_path] [criteria] [action]
[search_path]: The directory to start searching from (.— current folder,/— system root).[criteria]: The condition for the search (name, size, date, etc.). Can be combined using-a(AND) or-o(OR).[action]: What to do with the found files. If not specified,findsimply prints the paths.
Example: Find all files with the .conf extension in /etc and its subdirectories.
find /etc -name "*.conf"
💡 Tip: Always enclose the pattern in quotes (
"or') so the shell doesn't try to expand it before passing it tofind.
Step 2: Case-Insensitive Name Search
By default, -name is case-sensitive. For case-insensitive search, use -iname:
# Find Readme.md, README.md, readme.MD
find /path/to/project -iname "readme.md"
Step 3: Search by File Type
Use -type to filter by filesystem object type:
f— regular filed— directoryl— symbolic linkc— character deviceb— block device
Example: Find only directories named logs:
find / -type d -name "logs"
Step 4: Combining Criteria (Logical Operators)
Combine conditions for complex queries:
-a(AND) — by default, if conditions follow each other.-o(OR) — alternative.!or-not— negation.
Example: Find all .log files in /var/log that are larger than 10 MB AND were modified in the last 7 days:
find /var/log -name "*.log" -size +10M -mtime -7
Example 2: Find files with the .tmp OR .temp extension in the home directory:
find ~ -name "*.tmp" -o -name "*.temp"
⚠️ Important: When using
-o, you often need to group conditions with parentheses\( ... \)to set precedence. For example, search for.bakfiles NESTED insidecacheortempdirectories:find / -type d \( -name "cache" -o -name "temp" \) -exec find {} -name "*.bak" \;
Step 5: Search by File Size
The -size option uses suffixes:
c— bytesk— kilobytes (1024 bytes)M— megabytesG— gigabytes
Signs:
+— greater than specified-— less than specified- No sign — exact match (rarely used)
Example: Find files that are exactly 0 bytes (empty):
find /tmp -size 0c
Example: Find files between 500 MB and 2 GB:
find / -size +500M -size -2G
Step 6: Search by Date and Time
find works with days (not hours) by default. There are three main criteria:
-mtime N— when the file's content was modified N days ago.-atime N— when the file was accessed (read, executed) N days ago.-ctime N— when the file's metadata (permissions, owner) was changed N days ago.
Explanation of days:
-mtime 0— modified today (within the last 24 hours).-mtime -1— modified less than 24 hours ago (similar to "yesterday and today").-mtime +1— modified more than 48 hours ago (older than 2 days).
For searching by hours and minutes, use:
-mmin N— minutes since last modification.-amin N— minutes since last access.-cmin N— minutes since last metadata change.
Practical examples:
# Find all files modified in the last 2 hours (120 minutes)
find /var/www -mmin -120
# Find files not accessed for over 30 days (possibly ready for archiving)
find /home -atime +30
# Find files created yesterday (approximately 24-48 hours ago)
find /backup -mtime 1
Step 7: Search by Permissions and Owner
By permissions (perm):
-perm mode— exact permission match (e.g.,-perm 644).-perm -mode— all bits inmodemust be set (logical AND). For example,-perm -u=xfinds files where the owner has execute permission, regardless of other permissions.-perm /mode— at least one bit inmodeis set (logical OR). For example,-perm /u=x,g=wfinds files where the owner can execute OR the group can write.
Example: Find all executable files (x for anyone) in /usr/bin:
find /usr/bin -perm /111
Or, equivalently:
find /usr/bin -perm /a=x
By owner/group:
-user username— files owned by the user.-group groupname— files owned by the group.
Example: Find all files owned by the user www-data (common for web servers):
find /var -user www-data
Step 8: Performing Actions on Found Files
Search criteria are often combined with actions using -exec or -delete.
-exec: Executes the specified command for each found file. {} is replaced by the filename. Ends with \;.
# Find all .tmp files and delete them (CAUTION!)
find /tmp -name "*.tmp" -exec rm {} \;
# Find all .log files and compress them with gzip
find /var/log -name "*.log" -exec gzip {} \;
# Find files writable by the group and list their permissions
find / -type f -perm -g=w -exec ls -l {} \;
-delete: Deletes the found files. Be extremely careful! First, check the output without -delete.
# Safe method: first see what will be deleted
find /tmp -name "*.cache" -ls
# Then, if correct, delete
find /tmp -name "*.cache" -delete
-ok: Similar to -exec, but asks for confirmation before running each command.
find . -name "*.bak" -ok rm {} \;
# Will prompt: < rm ... > ? (y/n)
Step 9: Alternatives: locate and fd
locate — Fast Database-Based Search
Works much faster than find because it searches a daily-updated database (/var/lib/mlocate/mlocate.db) instead of the filesystem.
locate filename # Simple search
locate -i filename # Case-insensitive
locate -c filename # Only count of found files
Manually update the database (requires sudo):
sudo updatedb
⚠️ Important:
locatedoes not see files created after the lastupdatedb. Usefindfor very recent files.
fd — Modern, Fast, and User-Friendly find Replacement
Simplified syntax, colored output, ignores files from .gitignore by default.
fd pattern # Searches in current directory (recursively)
fd -e js # Finds files with .js extension
fd -g '*.py' # Glob pattern (like in shell)
fd -s +1M # By size (larger than 1 MB)
fd -t f # Files only (-t d for directories)
fd -I # Don't ignore hidden files (.gitignore by default)
Example: Find all Dockerfile instances (case-sensitive) in the project:
fd Dockerfile
Example: Find Python files modified in the last week:
fd -e py -c time -1w
Verifying the Result
After running find/locate/fd, ensure the output matches expectations:
- Check the full paths of found files. Did you find anything extra?
- For critical operations (deletion, modification), first review the list without actions (
-lsinfindor just output). - Ensure results aren't outdated (especially for
locate). If searching for a recently created file andlocatedoesn't find it — usefind. - Check access permissions. If the command finds nothing, try running with
sudo(if searching in system directories).
Common Issues
Issue: find returns nothing, but the file definitely exists.
Solution:
- Check the search path is correct. Ensure the directory containing the file is specified correctly (
.for current folder). - Check filename case when using
-name. Use-inamefor case-insensitive search. - Check permissions on parent directories. If you lack read (
r) permission on a directory,findcannot look inside. Trysudo find .... - Ensure the file isn't a symbolic link pointing to an inaccessible location. Use
-type lto search for links.
Issue: find is too slow on large disks.
Solution:
- Limit search depth with
-maxdepth N(max N levels of nesting) and-mindepth N(min N levels). For example,find / -maxdepth 3 -name "*.log"searches only the first three subdirectories of root. - Use
locatefor name-based searches if database freshness (usually one day) is acceptable. - Use
fd, which is optimized for speed and ignores unnecessary directories (.git,node_modules) by default. - Narrow the search path. Instead of
find /, search in a specific partition (find /home).
Issue: Need to find files containing specific text.
Solution: find isn't designed for this. Use grep:
grep -r "search_text" /path/to/search/
To search only among files with a specific extension:
grep -r --include="*.log" "ERROR" /var/log/
Or combine find and grep:
find . -name "*.py" -exec grep -l "def main" {} \;
# Finds all .py files containing the line "def main" and prints their names.
Issue: find outputs too many results; need only the count.
Solution: Add | wc -l (pipe to word count, lines):
find /var/log -name "*.log" | wc -l
Or use the built-in find option -printf '.' | wc -c (faster for huge numbers of files).
Issue: Need to find and process files with spaces or special characters in names.
Solution: Always use -exec or -print0 with xargs -0. Simple output (find . -name "*.txt") can break with spaces.
# Safe processing with xargs
find . -name "*.txt" -print0 | xargs -0 rm
# Or with -exec (safer)
find . -name "*.txt" -exec rm {} \;
The -print0 option outputs names separated by a NUL character (\0), and xargs -0 handles them correctly.