CakePHP provides filesystem utilities for working with files and directories efficiently. These utilities are split into two main classes:
Finder - A fluent, iterator-based API for discovering files and directories
Path - Static utilities for path manipulation
The Finder class provides a lazy, iterator-based approach to discovering files and directories
with a fluent interface for building complex queries. It’s memory-efficient and works consistently
across different operating systems.
Add a directory to search in. Can be called multiple times.
Find only files (returns iterator).
Find only directories (returns iterator).
Find both files and directories (returns iterator).
Enable or disable recursive directory traversal. Default is true.
Include files/directories matching a glob pattern. Multiple calls use OR logic.
Exclude files/directories matching a glob pattern. Multiple calls use OR logic.
Include files whose relative path matches a pattern (substring or regex). Multiple calls use OR logic.
Exclude files whose relative path matches a pattern (substring or regex). Multiple calls use OR logic.
Include files matching a glob pattern against the full relative path. Supports ** for recursive matching.
Exclude specific directories from traversal. More efficient than filtering.
Filter by directory depth using operators like EQUAL, LESS_THAN, GREATER_THAN, etc.
Apply custom filter callback. Receives SplFileInfo and relative path. Multiple calls use AND logic.
Exclude hidden files (files starting with .).
Find all PHP files in a directory:
use Cake\Utility\Fs\Finder;
$finder = (new Finder())
->in('src')
->name('*.php')
->files();
foreach ($files as $file) {
echo $file->getPathname();
}
Find directories while excluding certain ones:
$directories = (new Finder())
->in('src')
->exclude('vendor')
->exclude('tmp')
->directories();
By default, the Finder searches recursively. Use recursive(false) for top-level only:
$finder = (new Finder())
->in('src')
->recursive(false)
->files();
Include and exclude specific filename patterns:
$finder = (new Finder())
->in('src')
->name('*.php') // Include all PHP files
->notName('*Test.php') // Exclude test files
->notName('*Fixture.php') // Exclude fixtures
->files();
Filter by path containing specific strings or regex patterns:
$finder = (new Finder())
->in('src')
->path('Controller') // Include paths containing "Controller"
->notPath('Test') // Exclude paths containing "Test"
->path('/Controller\.php$/') // Or use regex patterns
->files();
Control traversal depth using type-safe operators:
use Cake\Utility\Fs\Enum\DepthOperator;
// Maximum depth of 3
$finder = (new Finder())
->in('src')
->depth(3, DepthOperator::LESS_THAN)
->files();
// Depth range (1, 2, or 3)
$finder = (new Finder())
->in('src')
->depth(0, DepthOperator::GREATER_THAN)
->depth(4, DepthOperator::LESS_THAN)
->files();
Available depth operators: EQUAL, NOT_EQUAL, LESS_THAN, GREATER_THAN,
LESS_THAN_OR_EQUAL, GREATER_THAN_OR_EQUAL.
Use glob patterns with ** for recursive matching:
$finder = (new Finder())
->in('.')
->pattern('src/**/*Controller.php')
->pattern('tests/**/*Test.php')
->files();
Glob syntax: * matches any characters except /, ** matches including /,
? matches single character, [abc] matches any character in set.
For complex filtering, use custom callbacks:
use SplFileInfo;
$finder = (new Finder())
->in('src')
->filter(fn(SplFileInfo $file) => $file->getSize() > 1024)
->filter(fn(SplFileInfo $file) => $file->getMTime() > strtotime('-1 week'))
->files();
The callback receives SplFileInfo and the relative path:
$finder = (new Finder())
->in('.')
->filter(function (SplFileInfo $file, string $relativePath) {
return str_starts_with($relativePath, 'src/Controller')
|| str_starts_with($relativePath, 'src/Model');
})
->files();
Combining multiple filters:
use Cake\Utility\Fs\Finder;
use Cake\Utility\Fs\Enum\DepthOperator;
$finder = (new Finder())
->in('src')
->in('plugins')
->name('*.php')
->notName('*Test.php')
->exclude('vendor')
->exclude('tmp')
->path('Controller')
->depth(5, DepthOperator::LESS_THAN)
->ignoreHiddenFiles()
->files();
foreach ($finder as $file) {
echo $file->getRealPath() . PHP_EOL;
}
The Path class provides static utilities for path manipulation.
Convert paths to use forward slashes.
Convert an absolute path to a relative path based on a base directory.
Join multiple path segments into a single path.
Test if a path matches a glob pattern. Supports *, **, ?, and [abc] syntax.
use Cake\Utility\Fs\Path;
// Normalize path separators
Path::normalize('path\\to\\file.php');
// Returns: 'path/to/file.php'
// Make relative paths
Path::makeRelative('/var/www/app/src/Controller/UsersController.php', '/var/www/app');
// Returns: 'src/Controller/UsersController.php'
// Join path segments
Path::join('src', 'Controller', 'UsersController.php');
// Returns: 'src/Controller/UsersController.php'
// Match glob patterns
Path::matches('*.php', 'test.php'); // true
Path::matches('src/**/*.php', 'src/Controller/UsersController.php'); // true
Path::matches('src/**/Test/*.php', 'src/Controller/UsersController.php'); // false