The symfony Cookbook

How to locate a file

symfony trainingBe trained by Sensio Labs, Join a symfony Workshop, Register for the next session

About

You are currently reading "The symfony Cookbook" which is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.

Search


powered by google

Chapter Content

Overview

The sfFinder class

Rules principle

Filter rules

Filter by name

Filter by size

Limiting the search depth

Excluding directories

Search starting point

Returning relative paths

You are currently browsing "The symfony Cookbook" in English for the 1.0 version. Switch to another version:
Creative Commons License This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.
Translation of this work into another language is explicitly allowed.

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");
  ...
}
 

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:

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');
 

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');
 

Questions & Feedback

If you find a typo or an error, please register and open a ticket.

If you need support or have a technical question, please post to the user mailing-list or to the forum.