How to Find Both Hidden and Non-Hidden Files in Linux Using find Command with PHP Extension


10 views

When working on Linux servers, developers often need to locate files with specific extensions across entire directory trees. The standard approach using find combined with grep has a significant limitation - it misses hidden files (those beginning with a dot).

The command sequence:

find . -type f | grep -i *.php

misses hidden files because:

  • The shell expands *.php before grep sees it
  • Globbing patterns don't match dotfiles by default

The most efficient method uses find's built-in pattern matching:

find . -type f -iname "*.php"

This command:

  • Recursively searches from current directory (.)
  • Finds only regular files (-type f)
  • Matches case-insensitive (-iname) PHP extensions
  • Includes both hidden and visible files

For more complex scenarios:

# Find PHP files modified in last 7 days
find . -type f -iname "*.php" -mtime -7

# Find PHP files with specific permission
find . -type f -iname "*.php" -perm 0644

# Combine multiple extensions
find . -type f $-iname "*.php" -o -iname "*.phps"$

# Exclude certain directories
find . -type f -iname "*.php" -not -path "./vendor/*"

For very large directories, using -name instead of -iname (case-sensitive) can be slightly faster:

find . -type f -name "*.php" -o -name ".*.php"

The -o operator combines both patterns, though -iname is generally more readable and maintainable.


When working with Linux servers, developers often need to locate files matching specific patterns. The common approach using find . -type f | grep -i *.php has a significant limitation - it misses hidden files (those beginning with a dot).

The issue stems from how shell globbing and grep patterns interact. Hidden files (like .config.php) don't match the simple *.php pattern because:

1. The dot prefix makes them "hidden" in Unix-like systems
2. Shell globbing doesn't include dotfiles by default
3. The grep pattern needs proper escaping for dots

Instead of piping to grep, we can use find's built-in pattern matching:

find . -type f -name "*.php" -o -name ".*.php"

This command efficiently finds both:

- regular.php
- .hidden.php
- subdir/normal.php
- subdir/.config.php

For case-insensitive matching (PHP, php, Php):

find . -type f $-iname "*.php" -o -iname ".*.php"$

You can extend this to include additional criteria like file size or modification time:

find . -type f $-iname "*.php" -o -iname ".*.php"$ -mtime -7 -size +1k

This finds PHP files (hidden or not) modified in the last 7 days and larger than 1KB.

For complex patterns, consider regular expressions:

find . -type f -regex ".*/\..*\.php$\|.*\.php$" -print

The native find patterns execute faster than piping to grep because:

- No additional process spawned (grep)
- Find's internal matching is optimized
- Less data transferred through pipes