How to find a file in linux from the command line
TechVertu » Blog » Software » How To Find a File or Directory in Linux From the Command Line

How To Find a File or Directory in Linux From the Command Line

Locating files quickly on a Linux system is a fundamental skill that separates confident administrators from those constantly frustrated by their filesystems. Whether you’re hunting for configuration files buried in /etc, tracking down space-hogging logs, or searching through thousands of source files for a specific function, knowing the right tools transforms what could be hours of manual browsing into seconds of targeted searching.

This guide walks you through the essential commands for finding files on Linux—from the venerable find utility to modern alternatives like fd and ripgrep. You’ll learn not just the syntax, but when to use each tool, how to combine them effectively, and how to avoid common pitfalls that can slow your system or accidentally modify important files.

TL;DR – Quick command reference

find [PATH_TO_BE_SEARCHED] -name "filename.txt"             # Find by exact name
find [PATH_TO_BE_SEARCHED] -iname "*.log"                   # Case-insensitive pattern
locate filename                                             # Fast database search
fd pattern [PATH_TO_BE_SEARCHED]                            # Modern find alternative
grep -r "search term" [PATH_TO_BE_SEARCHED]                 # Search file contents recursively
find [PATH_TO_BE_SEARCHED] -type f -size +100M              # Files larger than 100MB
find [PATH_TO_BE_SEARCHED] -mtime -7 -name "*.tmp" -delete  # Find and delete files modified in last 7 days

Using the find Command

The find command is the Swiss Army knife of file searching in Linux. Present on virtually every Unix-like system, it recursively searches directory trees based on remarkably flexible criteria. Unlike database-driven tools, find performs real-time filesystem traversal, ensuring you always see current results.

Basic syntax and searching by name

The fundamental structure follows:

find [starting-path] [test-expression] [action]
find /home/user/documents -name "report.pdf"

This searches /home/user/documents all subdirectories for files named exactly “report.pdf”. The -name test is case-sensitive, so “Report.pdf” wouldn’t match. For case-insensitive searching, use-iname:

find /var/log -iname "*.LOG"

This finds files ending in .log, .LOG, .Log, or any other case variation—particularly useful when dealing with files created on case-insensitive filesystems or by inconsistent applications. Wildcard patterns work as expected: * matches any characters,? Matches a single character, and [] matches character ranges. Remember to quote patterns to prevent shell expansion:

find ~/projects -name "test_*.py"

Filtering by file type

The -type flag restricts results to specific filesystem objects:

find /etc -type f -name "*.conf"    # Regular files only
find /tmp -type d -name "cache*"    # Directories only
find /dev -type l                    # Symbolic links
find /var -type s                    # Sockets

This proves invaluable when you need to distinguish between a directory called backup and a file with the same name, or when listing only symbolic links for auditing purposes.

Searching by size

The -size flag accepts various units (c=bytes, k=kilobytes, M=megabytes, G=gigabytes):

find /var/log -type f -size +100M           # Larger than 100MB
find ~/downloads -type f -size -10k         # Smaller than 10KB
find /tmp -type f -size 0                   # Exactly 0 bytes (empty files)

Size specifications use + for “greater than”, - for “less than”, and no prefix for “exactly”. Finding oversized log files before they consume your disk space is a routine administrative task:

find /var/log -type f -size +500M -exec ls -lh {} \;

Filtering by modification and change time

Time-based searches use -mtime (modification time), -ctime (metadata change time), and -atime (access time). Values represent 24-hour periods:

find /home/user -type f -mtime -7           # Modified in last 7 days
find /tmp -type f -mtime +30                # Modified more than 30 days ago
find /var/backups -mtime 0                  # Modified today (last 24hrs)

For more precise control, -newermt accepts human-readable dates:

find /var/log -newermt "2025-10-01" -type f
find ~/documents -newermt "1 week ago"

This syntax, whilst not POSIX standard, works on GNU findutils and proves tremendously convenient for incident investigation or compliance audits.

Searching by permissions

The -perm flag matches files based on permission bits. Three modes exist: exact (-perm 644), all-set (-perm -644), and any-set (-perm /644):

find /var/www -type f -perm 777              # Exactly 777 (security risk!)
find /home -type f -perm -u=w -perm -g=w     # User AND group writable
find /tmp -type f -perm /o=w                 # World-writable (any)

Finding world-writable files represents a common security audit task:

find /var/www -type f \( -perm -002 -o -perm -020 \) -ls

You can also search by owner with -uid or -user:

find /home -type f -user oldemployee         # Files owned by specific user
find /tmp -uid 1000 -mtime +7 -delete        # Cleanup files from UID 1000

Executing commands with -exec and -delete

The -exec action runs commands on matched files. The {} placeholder represents the found filename, and the command must end with \; or +:

find /tmp -name "*.tmp" -mtime +7 -exec rm {} \;

Using \; runs the command once per file (slower but safer), whilst + batches multiple files into one invocation (faster but potentially problematic with argument length limits). For deletions, -delete offers a safer built-in alternative:

find /var/cache -type f -name "*.cache" -mtime +30 -delete

Critical safety tip: Always test with -ls or -print before using -delete or -exec rm:

find /var/log -name "*.log" -mtime +90 -ls    # Verify first!
find /var/log -name "*.log" -mtime +90 -delete # Then delete

Handling filenames with spaces and special characters

Filenames containing spaces, newlines, or special characters can break scripts. The combination of -print0 (null-separated output) and xargs -0 handles this correctly:

find /media/backup -type f -name "*.bak" -print0 | xargs -0 rm
find ~/music -type f -name "*.mp3" -print0 | xargs -0 -I {} cp {} /backup/music/

The -I {} flag for xargs defines a placeholder, similar to -exec, but xargs batches commands more efficiently.

Optimising find with -prune and -fstype

Excluding directories improves performance and prevents unnecessary traversal:

find / -path /proc -prune -o -path /sys -prune -o -name "config.yaml" -print

The -fstype flag restricts searches to specific filesystem types, preventing find from searching network mounts or temporary filesystems:

find / -fstype ext4 -o -fstype xfs -name "large-file.bin"

Combining these techniques dramatically reduces search time when working from root directories.

Using -printf for custom output

The -printf action formats output with custom specifiers:

find /var/log -type f -printf "%s %p\n" | sort -n    # Size and path, sorted
find ~/documents -name "*.pdf" -printf "%TY-%Tm-%Td %p\n"  # Date and filename

Format codes include %s (size), %p (path), %T (time), %u (username), and many others—consult man find for comprehensive documentation.

Using locate and updatedb

The locate command searches a pre-built database rather than scanning the filesystem in real-time, making it dramatically faster for simple name searches:

locate sshd_config
locate -i readme.txt                         # Case-insensitive
locate -b "\config.yaml"                     # Basename only (no path matching)

On most distributions, updatedb runs nightly via cron, indexing the entire filesystem. This introduces a crucial limitation: locate cannot find files created since the last database update.

Manually update the database with:

sudo updatedb

This process can take several minutes on large filesystems. The database typically resides in /var/lib/mlocate/mlocate.db or similar locations.

When to use locate:

  • Quick searches for known filenames across the entire system
  • Files that don’t change frequently
  • Initial reconnaissance before narrowing down with find

Limitations:

  • Results may be stale
  • Doesn’t search inside files
  • Limited filtering compared to find
  • Security: respects user permissions but shows file existence

The performance trade-off favours locate for simple queries, but find remains essential for complex criteria, recent changes, or guaranteed current results.

Modern alternatives: fd and ripgrep

The fd command

fd is a modern, user-friendly alternative to find, written in Rust. It offers sensible defaults: case-insensitive by default, ignores .gitignore patterns, and uses intuitive syntax:

fd config.yaml                               # Simple search
fd -e log                                    # All .log files
fd -H -I pattern                             # Include hidden (-H) and ignored (-I) files
fd '^test_.*\.py$' ~/projects                # Regex patterns

Install via package managers:

sudo apt install fd-find      # Debian/Ubuntu (binary named fdfind)
sudo dnf install fd-find      # Fedora/CentOS/RedHat/Rocky Linux

fd excels in developer workflows where .gitignore awareness prevents searching through node_modules or build artifacts. However, find remains superior for advanced permissions searches and portable scripts.

Using ripgrep for content searching

Whilst fd finds files by name, ripgrep (rg) searches file contents at extraordinary speed:

rg "function authenticate" ~/projects        # Search for function name
rg -i "error" /var/log                       # Case-insensitive content search
rg -t python "import requests"               # Search only Python files

ripgrep automatically respects .gitignore, searches recursively, and displays results with syntax highlighting. Installation:

sudo apt install ripgrep      # Debian/Ubuntu
sudo dnf install ripgrep      # Fedora/CentOS/RedHat/Rocky Linux

The tool dramatically outperforms traditional grep on large codebases, making it indispensable for developers searching thousands of files.

Searching file contents with grep

When modern tools aren’t available, grep remains the standard for content searching:

grep -r "ERROR" /var/log                     # Recursive search
grep -ri "todo" ~/projects                   # Case-insensitive recursive
grep -rn "import sys" ~/code                 # Show line numbers
grep -rl "password" /etc                     # List files only (no content)

The -r flag enables recursive directory traversal, -i ignores case, -n displays line numbers, and -l lists matching files without showing the matched lines.

Combining find with grep

For more control, pipe find results to grep:

find /var/log -name "*.log" -type f -exec grep -H "authentication failure" {} \;

The -H flag forces grep to print filenames even when processing single files, crucial when using -exec. A more efficient approach uses xargs:

find ~/projects -name "*.js" -print0 | xargs -0 grep -n "console.log"

This batches multiple files per grep invocation, significantly improving performance on large result sets.

Real-world practical scenarios

Scenario 1: Find and archive large log files

Your /var/log partition is filling up. Find logs older than 30 days, larger than 50MB, compress them, and verify:

find /var/log -type f -name "*.log" -mtime +30 -size +50M -print0 | \
xargs -0 -I {} sh -c 'gzip -9 "{}" && echo "Compressed: {}"'

This finds matching logs, compresses each with maximum compression (-9), and confirms each operation.

Scenario 2: Locate a missing SSH configuration file

You’ve lost your SSH key or config file somewhere in your home directory:

find ~ -name "id_rsa*" -o -name "id_ed25519*" -o -name "ssh_config" 2>/dev/null

The 2>/dev/null redirects permission errors (from directories you can’t read) to silence. The -o operators create logical OR conditions between patterns.

Alternatively, using fd:

fd -H -I 'id_rsa|id_ed25519|ssh_config' ~

Scenario 3: Find function definition across project files

You’re debugging and need to locate where validate_user() is defined in a large Python project:

rg -t python "def validate_user" ~/projects/webapp

Or using traditional tools:

find ~/projects/webapp -name "*.py" -print0 | xargs -0 grep -n "def validate_user"

The ripgrep version completes in milliseconds, whilst the find+grep combination may take seconds on large projects—but the latter works on any system without additional installations.

Combined workflow examples

Find and change permissions

Reset permissions on all PHP files to 644, directories to 755:

find /var/www/html -type f -name "*.php" -exec chmod 644 {} +
find /var/www/html -type d -exec chmod 755 {} +

The + terminator batches files, making this significantly faster than \; on large directory trees.

Find and delete empty directories

Cleanup empty directories left behind after moving files:

find /tmp -type d -empty -delete

Add -depth to process directories depth-first, ensuring parent directories are evaluated after children:

find /var/cache -depth -type d -empty -delete

Find recently modified files and copy to backup

Backup files modified in the last 24 hours:

find ~/documents -type f -mtime 0 -print0 | \
xargs -0 -I {} cp --parents {} /backup/daily/

The --parents flag preserves directory structure in the destination.

Troubleshooting and security considerations

Permission denied errors

When searching from /, you’ll encounter directories your user cannot read. Redirect errors:

find / -name "*.conf" 2>/dev/null

Or run with elevated privileges when appropriate:

sudo find /root -name "id_rsa"

Security warning: Be cautious with sudo find combined with -exec or -delete—you can inadvertently damage system files.

By default, find doesn’t follow symbolic links. To follow them whilst avoiding loops, use -L with caution:

find -L /var -name "*.log"

If you encounter “Filesystem loop detected” warnings, add -maxdepth to limit recursion:

find -L /var -maxdepth 5 -name "*.log"

Searching only local filesystems

Prevent searches from traversing network mounts or removable media:

find / -xdev -type f -size +1G

The -xdev flag (or -mount) restricts find to the same filesystem as the starting directory—crucial for performance and avoiding hanging on unresponsive network shares.

Performance tips

  1. Start searches from the most specific directory possible rather than / to reduce traversal time.
  2. Use -type early in the expression as it’s evaluated quickly:

bash

find /var -type f -name "*.log"    # Faster
find /var -name "*.log" -type f    # Slower
  1. Prune unnecessary directories like /proc, /sys, and /dev:

bash

find / \( -path /proc -o -path /sys -o -path /dev \) -prune -o -name "*.conf" -print
  1. Use locate for initial reconnaissance, then narrow down with find.
  2. Limit depth with -maxdepth when you know the target location:

bash

  find /etc -maxdepth 2 -name “*.conf”

  1. Consider fd or ripgrep for developer workstations where performance matters and .gitignore awareness is valuable.

Further reading

For a deeper exploration of Linux file searching techniques, consult these authoritative resources:

  1. GNU Findutils Manual – The definitive reference for find, locate, and xargs: https://www.gnu.org/software/findutils/manual/html_node/index.html
  2. The Linux Documentation Project (TLDP) – Comprehensive guides on shell scripting and command-line tools: https://tldp.org/
  3. Arch Linux Wiki: Core Utilities – Excellent practical examples and troubleshooting for common utilities: https://wiki.archlinux.org/title/Core_utilities

The find command’s flexibility, whilst initially daunting, becomes second nature with practice. Modern alternatives like fd and ripgrep offer compelling improvements for specific use cases, but mastering find ensures you can work effectively on any Linux system, regardless of installed tools. Start with simple name searches, gradually incorporate time and size filters, and soon you’ll be crafting complex one-liners that would have taken hours of manual searching.

Subscribe for Latest Tech Insights & Company News

anything else?

Lets Talk!

If you have additional comments or questions about this article, you can share them in this section.

Your email address will not be published. Required fields are marked *


Scroll to Top