Skip to content
Caution: You are browsing the legacy symfony 1.x part of this website.

How to locate a file

Symfony version
Language

Overview

Some scripts in your applications may need to access files without necessarily knowing where they are. If you were using a bash command, you could use find to find them. In symfony, you can do it just as easily with the sfFinder class. Doing a complex search is just a matter of adding new search criteria, and the result is a simple array if file paths.

The sfFinder class

The sfFinder class if a file finder class based on the Perl File::Find::Rule module. It can find either files or directories (or both), and filters the search by a set of user-defined rules. The basic usage is the following:

  1. Create a sfFinder object for your search by calling the class method type(). You must precise what kind of result you expect (either file, dir or any)

    $finder = sfFinder::type('file');
  2. Add rules to refine your search and decrease the number of results

    $finder = $finder->name('*.php');
  3. Launch the search by calling the in() method, setting the root directory of the search as argument

    $files = $finder->in('/home/production/myproject');

All these method calls can be chained to one single line, which is often easier to read:

$files = sfFinder::type('file')->name('*.php')->in('/home/production/myproject');
// can be read as
// find files with name matching '*.php' in the '/home/production/myproject' directory

The in() method returns an array of files, that can easily be used for file manipulation:

foreach ($files as $file)
{
  $handle = fopen($file, "r");
  ...
}

note

The sfFinder class is autoloaded and doesn't need to be required in your scripts.

Rules principle

The rules used to refine the search are written as method calls of an sfFinder object. All methods return the current sfFinder object to allow easy chaining.

$finder1 = sfFinder::type('file')->name('*.php');                   // is a sfFinder object
$finder2 = sfFinder::type('file')->name('*.php')->size('> 10K');    // is also a sfFinder object
$files = $finder1->in('/home/production/myproject');                // is an array of file paths

All rules may be invoked several times, except for the in() method.

Some rules are cumulative (name() for example) whereas others are destructive (like maxdepth()). For destructive rules, only the most recent method call counts:

// this one will filter for file names satisfying both conditions
$finder = sfFinder::type('file')->name('*.php')->name('*Success.*');
// same as
$finder = sfFinder::type('file')->name('*Success.php');
 
// here, only the last call is taken into account
$finder = sfFinder::type('file')->maxdepth(5)->maxdepth(3);
// same as
$finder = sfFinder::type('file')->maxdepth(3);

Filter rules

Filter by name

To filter the results on file names, add calls to the name() method with patterns in glob or regular expression format:

$finder = sfFinder::type('file')->name('*.php');
$finder = sfFinder::type('file')->name('/.*\.php/');

You can even exclude certain file names from the result, doing negative filtering with the not_name() method:

$finder = sfFinder::type('file')->not_name('Base*');
$finder = sfFinder::type('file')->name('/^Base.*$/');

Filter by size

You can filter your search on file size by calling the size() method, which expects a string containing a comparison as argument. The method also understands magnitudes:

// search only for files bigger than 10 kilobytes
$finder = sfFinder::type('file')->size('> 10K');
// search only for files smaller than 1 kilobyte, or exactly that
$finder = sfFinder::type('file')->size('<= 1Ki');
// search only for files being 123 bytes of size
$finder = sfFinder::type('file')->size(123);

The symbols used for magnitude are the binary prefix defined by the International System of Units.

Limiting the search depth

By default, a search made by the sfFinder object is recursive and scans all the subdirectories. You can override this default behaviour by using the maxdepth() method to set the maximum depth of search in the file tree structure:

// search in directory and subdirectories
$finder = sfFinder::type('file');
// search only in the directory passed to the in() method,
// and not in any subdirectory
$finder = sfFinder::type('file')->maxdepth(1);

Of course, you can also specify a minimum depth by calling the mindepth() method.

By default, the minimum depth is 0 and the maximum depth is infinite (or close to).

Excluding directories

If you want to exclude directories from the search, you can use two methods:

  • the prune() method stops the search in the part of the tree structure where the pattern given as argument is found. See it as an interdiction to go and see what's in a directory:

    // ignore the content of '.svn' folders
    $finder = sfFinder::type('any')->prune('.svn');

    The finder doesn't go deeper in any of the .svn folders, but the .svn folders themselves are still part of the results.

  • the discard() method removes the files or folders that match the argument from the result, but doesn't stop the tree structure exploration.

    // remove the '.svn' folders from the result
    $finder = sfFinder::type('any')->discard('.svn');

These two methods are often used in conjunction, when a directory and its content need to be excluded from a search:

// remove the '.svn' folders and their content from the result
$finder = sfFinder::type('any')->prune('.svn')->discard('.svn');

tip

To exclude the files and directories added by version control programs, sfFinder provides a shortcut method: ignore_version_control(). It will prune and discard and prune all files and directories looking like .svn, CVS, _darcs, .arch-params, .monotone, and .bzr.

Search starting point

The in() method is used to specify where the sfFinder has to look for files or directories. It can take a file path or an array of file paths as argument:

// search in a single location
$files = $finder->in('/home/production/myproject');
// search in several locations
$files = $finder->in(array('/home/production/myproject', '/home/production/myotherproject'));

It can accept either absolute or relative paths:

// absolute path
$files = $finder->in('/home/production/myproject');
// relative path
$files = $finder->in('../projects/myproject');

Returning relative paths

By default, the paths returned by the in() method are absolute paths. You can choose to receive an array of relative paths in place, by chaining the call to the relative() method before calling in():

// paths results are relative to the root directory
$files = $finder->in('/home/production/myproject');
// paths results are relative to the current directory,
// i.e. the directory of the current script
$files = $finder->relative()->in('/home/production/myproject');

This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.