The Finder Component
Warning: You are browsing the documentation for Symfony 3.x, which is no longer maintained.
Read the updated version of this page for Symfony 7.1 (the current stable version).
The Finder component finds files and directories via an intuitive fluent interface.
Installation
1
$ composer require symfony/finder:^3.4
Note
If you install this component outside of a Symfony application, you must
require the vendor/autoload.php
file in your code to enable the class
autoloading mechanism provided by Composer. Read
this article for more details.
Usage
The Finder class finds files and/or directories:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in(__DIR__);
foreach ($finder as $file) {
// dumps the absolute path
var_dump($file->getRealPath());
// dumps the relative path to the file, omitting the filename
var_dump($file->getRelativePath());
// dumps the relative path to the file
var_dump($file->getRelativePathname());
}
The $file
is an instance of SplFileInfo
which extends PHP's own SplFileInfo to provide methods to work with relative
paths.
The above code prints the names of all the files in the current directory recursively. The Finder class uses a fluent interface, so all methods return the Finder instance.
Tip
A Finder instance is a PHP IteratorAggregate. So, in addition to iterating over the
Finder with foreach
, you can also convert it to an array with the
iterator_to_array function, or get the number of items with
iterator_count.
Caution
The Finder
object doesn't reset its internal state automatically.
This means that you need to create a new instance if you do not want
to get mixed results.
Caution
When searching through multiple locations passed to the
in() method, a separate iterator
is created internally for every location. This means we have multiple result
sets aggregated into one.
Since iterator_to_array uses keys of result sets by default,
when converting to an array, some keys might be duplicated and their values
overwritten. This can be avoided by passing false
as a second parameter
to iterator_to_array.
Criteria
There are lots of ways to filter and sort your results. You can also use the hasResults() method to check if there's any file or directory matching the search criteria.
3.4
The hasResults()
method was introduced in Symfony 3.4.
Location
The location is the only mandatory criteria. It tells the finder which directory to use for the search:
1
$finder->in(__DIR__);
Search in several locations by chaining calls to in():
1 2 3 4 5
// search inside *both* directories
$finder->in([__DIR__, '/elsewhere']);
// same as above
$finder->in(__DIR__)->in('/elsewhere');
Use wildcard characters to search in the directories matching a pattern:
1
$finder->in('src/Symfony/*/*/Resources');
Each pattern has to resolve to at least one directory path.
Exclude directories from matching with the exclude() method:
1 2
// directories passed as argument must be relative to the ones defined with the in() method
$finder->in(__DIR__)->exclude('ruby');
It's also possible to ignore directories that you don't have permission to read:
1
$finder->ignoreUnreadableDirs()->in(__DIR__);
As the Finder uses PHP iterators, you can pass any URL with a supported protocol:
1 2 3 4 5
// always add a trailing slash when looking for in the FTP root dir
$finder->in('ftp://example.com/');
// you can also look for in a FTP directory
$finder->in('ftp://example.com/pub/');
And it also works with user-defined streams:
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\Finder\Finder;
$s3 = new \Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper('s3');
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
// ... do something with the file
}
Note
Read the Streams documentation to learn how to create your own streams.
Files or Directories
By default, the Finder returns both files and directories. If you need to find either files or directories only, use the files() and directories() methods:
1 2 3
$finder->files();
$finder->directories();
If you want to follow links, use the followLinks()
method:
1
$finder->files()->followLinks();
By default, the iterator ignores popular VCS files. This can be changed with
the ignoreVCS()
method:
1
$finder->ignoreVCS(false);
Sorting
Sort the result by name or by type (directories first, then files):
1 2 3
$finder->sortByName();
$finder->sortByType();
Sort the files and directories by the last accessed, changed or modified time:
1 2 3 4 5
$finder->sortByAccessedTime();
$finder->sortByChangedTime();
$finder->sortByModifiedTime();
Note
Notice that the sort*
methods need to get all matching elements to do
their jobs. For large iterators, it is slow.
You can also define your own sorting algorithm with sort()
method:
1 2 3
$finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) {
return strcmp($a->getRealPath(), $b->getRealPath());
});
File Name
Restrict files by name with the name() method:
1
$finder->files()->name('*.php');
The name()
method accepts globs, strings, or regexes:
1
$finder->files()->name('/\.php$/');
The notName()
method excludes files matching a pattern:
1
$finder->files()->notName('*.rb');
File Contents
Restrict files by contents with the contains() method:
1
$finder->files()->contains('lorem ipsum');
The contains()
method accepts strings or regexes:
1
$finder->files()->contains('/lorem\s+ipsum$/i');
The notContains()
method excludes files containing given pattern:
1
$finder->files()->notContains('dolor sit amet');
Path
Restrict files and directories by path with the path() method:
1 2 3 4
// matches files that contain "data" anywhere in their paths (files or directories)
$finder->path('data');
// for example this will match data/*.xml and data.xml if they exist
$finder->path('data')->name('*.xml');
On all platforms slash (i.e. /
) should be used as the directory separator.
The path()
method accepts a string or a regular expression:
1 2
$finder->path('foo/bar');
$finder->path('/^foo\/bar/');
Internally, strings are converted into regular expressions by escaping slashes and adding delimiters:
1 2
dirname ===> /dirname/
a/b/c ===> /a\/b\/c/
The notPath() method excludes files by path:
1
$finder->notPath('other/dir');
File Size
Restrict files by size with the size() method:
1
$finder->files()->size('< 1.5K');
Restrict by a size range by chaining calls:
1
$finder->files()->size('>= 1K')->size('<= 2K');
The comparison operator can be any of the following: >
, >=
, <
, <=
,
==
, !=
.
The target value may use magnitudes of kilobytes (k
, ki
), megabytes
(m
, mi
), or gigabytes (g
, gi
). Those suffixed with an i
use
the appropriate 2**n
version in accordance with the IEC standard.
File Date
Restrict files by last modified dates with the date() method:
1
$finder->date('since yesterday');
The comparison operator can be any of the following: >
, >=
, <
, <=
,
==
. You can also use since
or after
as an alias for >
, and
until
or before
as an alias for <
.
The target value can be any date supported by the strtotime function.
Directory Depth
By default, the Finder recursively traverse directories. Restrict the depth of traversing with depth():
1 2
$finder->depth('== 0');
$finder->depth('< 3');
Custom Filtering
To restrict the matching file with your own strategy, use filter():
1 2 3 4 5 6 7 8
$filter = function (\SplFileInfo $file)
{
if (strlen($file) > 10) {
return false;
}
};
$finder->files()->filter($filter);
The filter()
method takes a Closure as an argument. For each matching file,
it is called with the file as a SplFileInfo
instance. The file is excluded from the result set if the Closure returns
false
.
Reading Contents of Returned Files
The contents of returned files can be read with getContents():
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in(__DIR__);
foreach ($finder as $file) {
$contents = $file->getContents();
// ...
}