The Finder Component
Note
If you install this component outside of a Symfony application, you mustrequire the file in your code to enable the classautoloading mechanism provided by Composer. Readthis article for more details.
Usage
The Finder
class finds files and/ordirectories:
- use Symfony\Component\Finder\Finder;
- $finder = new Finder();
- // find all files in the current directory
- $finder->files()->in(__DIR__);
- // check if there are any search results
- if ($finder->hasResults()) {
- // ...
- }
- foreach ($finder as $file) {
- $absoluteFilePath = $file->getRealPath();
- $fileNameWithExtension = $file->getRelativePathname();
- // ...
- }
The $file
variable is an instance of which extends PHP's own
SplFileInfo
to provide methods to work with relative paths.
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 wantto get mixed results.
The component provides lots of methods to define the search criteria. They allcan be chained because they implement a .
The location is the only mandatory criteria. It tells the finder whichdirectory to use for the search:
- $finder->in(__DIR__);
Search in several locations by chaining calls toin()
:
- // search inside *both* directories
- $finder->in([__DIR__, '/elsewhere']);
- // same as above
- $finder->in(__DIR__)->in('/elsewhere');
Use *
as a wildcard character to search in the directories matching apattern (each pattern has to resolve to at least one directory path):
- $finder->in('src/Symfony/*/*/Resources');
Exclude directories from matching with the method:
- // 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:
- $finder->ignoreUnreadableDirs()->in(__DIR__);
As the Finder uses PHP iterators, you can pass any URL with a supportedPHP wrapper for URL-style protocols (ftp://
, zlib://
, etc.):
- // 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:
- use Symfony\Component\Finder\Finder;
- // register a 's3://' wrapper with the official AWS SDK
- $s3Client = new Aws\S3\S3Client([/* config options */]);
- $s3Client->registerStreamWrapper();
- $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
- }
Read the documentation to learn how to create your own streams.
Files or Directories
By default, the Finder returns files and directories; but the and
directories()
methods control that:
- // look for files only; ignore directories
- $finder->files();
- // look for directories only; ignore files
- $finder->directories();
- $finder->files()->followLinks();
Version Control Files
Version Control Systems (or "VCS" for short), such as Git and Mercurial,create some special files to store their metadata. Those files are ignored bydefault when looking for files and directories, but you can change this with theignoreVCS()
method:
- $finder->ignoreVCS(false);
If the search directory contains a .gitignore
file, you can reuse thoserules to exclude files and directories from the results with the method:
New in version 4.3: The ignoreVCSIgnored()
method was introduced in Symfony 4.3.
Find files by name with thename()
method:
- $finder->files()->name('*.php');
The name()
method accepts globs, strings, regexes or an array of globs,strings or regexes:
- $finder->files()->name('/\.php$/');
Multiple filenames can be defined by chaining calls or passing an array:
- $finder->files()->name('*.php')->name('*.twig');
- // same as above
- $finder->files()->name(['*.php', '*.twig']);
The notName()
method excludes files matching a pattern:
- $finder->files()->notName('*.rb');
Multiple filenames can be excluded by chaining calls or passing an array:
- $finder->files()->notName('*.rb')->notName('*.py');
- // same as above
- $finder->files()->notName(['*.rb', '*.py']);
File Contents
Find files by content with thecontains()
method:
- $finder->files()->contains('lorem ipsum');
The contains()
method accepts strings or regexes:
- $finder->files()->contains('/lorem\s+ipsum$/i');
The notContains()
method excludes files containing given pattern:
- $finder->files()->notContains('dolor sit amet');
Path
Find files and directories by path with thepath()
method:
- // 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');
Use the forward slash (i.e. /
) as the directory separator on all platforms,including Windows. The component makes the necessary conversion internally.
The path()
method accepts a string, a regular expression or an array ofstrings or regulars expressions:
- $finder->path('foo/bar');
- $finder->path('/^foo\/bar/');
Multiple paths can be defined by chaining calls or passing an array:
- $finder->path('data')->path('foo/bar');
- // same as above
- $finder->path(['data', 'foo/bar']);
Internally, strings are converted into regular expressions by escaping slashesand adding delimiters:
The method excludes filesby path:
Multiple paths can be excluded by chaining calls or passing an array:
- $finder->notPath('first/dir')->notPath('other/dir');
- // same as above
- $finder->notPath(['first/dir', 'other/dir']);
New in version 4.2: Support for passing arrays to notPath()
was introduced in Symfony4.2
Find files by size with thesize()
method:
- $finder->files()->size('< 1.5K');
Restrict by a size range by chaining calls or passing an array:
- $finder->files()->size('>= 1K')->size('<= 2K');
- // same as above
- $finder->files()->size(['>= 1K', '<= 2K']);
The target value may use magnitudes of kilobytes (k
, ki
), megabytes(m
, mi
), or gigabytes (g
, gi
). Those suffixed with an i
usethe appropriate 2**n
version in accordance with the .
File Date
Find files by last modified dates with the method:
- $finder->date('since yesterday');
Restrict by a date range by chaining calls or passing an array:
- $finder->date('>= 2018-01-01')->date('<= 2018-12-31');
- // same as above
- $finder->date(['>= 2018-01-01', '<= 2018-12-31']);
The comparison operator can be any of the following: >
, >=
, <
,<=
, ==
. You can also use since
or after
as an alias for >
,and until
or as an alias for <
.
The target value can be any date supported by strtotime
.
Directory Depth
By default, the Finder recursively traverses directories. Restrict the depth oftraversing with depth()
:
- $finder->depth('== 0');
- $finder->depth('< 3');
Restrict by a depth range by chaining calls or passing an array:
- $finder->depth('> 2')->depth('< 5');
- // same as above
- $finder->depth(['> 2', '< 5']);
To filter results with your own strategy, use:
- $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 returnsfalse
.
Sorting Results
Sort the results by name or by type (directories first, then files):
- $finder->sortByName();
- $finder->sortByType();
Tip
By default, the sortByName()
method uses the strcmp
PHPfunction (e.g. file1.txt
, file10.txt
, file2.txt
). Pass true
as its argument to use PHP's algorithm instead (e.g.file1.txt
, file2.txt
, file10.txt
).
Sort the files and directories by the last accessed, changed or modified time:
- $finder->sortByAccessedTime();
- $finder->sortByChangedTime();
- $finder->sortByModifiedTime();
You can also define your own sorting algorithm with the sort()
method:
- $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) {
- return strcmp($a->getRealPath(), $b->getRealPath());
- });
You can reverse any sorting by using the reverseSorting()
method:
Note
Notice that the sort*
methods need to get all matching elements to dotheir jobs. For large iterators, it is slow.
A Finder instance is an IteratorAggregate
PHP class. So, in additionto iterating over the Finder results with foreach
, you can also convert itto an array with the function, or get thenumber of items with
iterator_count
.
If you call to the method morethan once to search through multiple locations, pass
false
as a secondparameter to iterator_to_array
to avoid issues (a separateiterator is created for each location and, if you don't pass false
to, keys of result sets are used and some of themmight be duplicated and their values overwritten).
Reading Contents of Returned Files
- use Symfony\Component\Finder\Finder;
- $finder = new Finder();
- $finder->files()->in(__DIR__);
- foreach ($finder as $file) {
- $contents = $file->getContents();
- }