Finding files and directories in PHP with Symfony2 Finder component

Warning: This blog post was written a long time ago and might be no longer relevant.
Photo by Paul Watson: http://flic.kr/p/9HpBfj

Symfony Finder component makes the task of finding files and directories less tedious. It supports filtering by name, pattern, size, date of modification and few other criteria. As a result we get objects of class SplFileInfo which offers convenient way of retrieving file and directory details.

Note: Code used in this post is available on github: https://github.com/jakzal/SymfonyComponentsExamples

Installation

You can either install it from the Symfony PEAR channel or grab it directly from github. For the purpose of this article we'll clone the sources to the vendor/ directory of the project.

git clone https://github.com/symfony/Finder.git vendor/Symfony/Component/Finder

We'll let Symfony ClassLoader component to take care of the class autoloading. Read more about it in the "Autoloading classes in an any PHP project with Symfony2 ClassLoader component".

Following code is sufficient to load classes from any Symfony component (assuming components are put into the vendor/Symfony/Component directory):

<?php
// src/autoload.php
require_once __DIR__.'/../vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php';

$loader = new Symfony\Component\ClassLoader\UniversalClassLoader();
$loader->registerNamespaces(array(
    'Symfony' => __DIR__.'/../vendor',
    'PSS'     => __DIR__
));
$loader->register();

Example usage

Basically all we'll ever need is to create a Finder object with create() method and use fluent interface to define what we're looking for. It's best to review the Finder class for available filtering and sorting methods.

For example, to list all Symfony components installed in vendor/Symfony/Component directory we could write the following script:

<?php
// finderdir.php
require_once __DIR__.'/src/autoload.php';

use Symfony\Component\Finder as Finder;

$components = Finder\Finder::create()
    ->directories()
    ->depth(0)
    ->in('vendor/Symfony/Component');

echo "Installed Symfony components:\n";
foreach ($components as $dir) {
    printf("* %s \n", $dir->getFilename());
}

To show more sophisticated example, here's how we'd search for files matching the /^He.+Command.php$/ pattern, which are smaller than 4kb and were modified till yesterday. Results will be sorted by file name and we'll look for them in the current directory:

<?php
// finder.php
require_once __DIR__.'/src/autoload.php';

use Symfony\Component\Finder as Finder;

$files = Finder\Finder::create()
    ->files()
    ->name('/^He.+Command.php$/')
    ->size('<4k')
    ->date('until yesterday')
    ->sortByName()
    ->in('.');

echo "Command files starting with 'He' below 4k modified untill yesterday:\n";
foreach ($files as $file) {
    printf("* %s %s\n", $file->getFilename(), date('Y-m-d H:i', $file->getMTime()));
}

Easy, isn't it?

Finder component gives us a really nice and flexible way to search and than to iterate through files and directories. It's one of those handy libraries which we probably won't use often. Once we need it, however, we may find it a real time saver.