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


2 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