Finder: Filesystem Search
Need to go through directories on disk? Are you looking for files in them? The Nette\Utils\Finder class will make it as easy as possible.
All examples assume the following class alias is defined:
use Nette\Utils\Finder;
Installation
Download and install the package using Composer:
composer require nette/finder
Searching for Files
How to find all *.txt
files in $dir
directory and all its subdirectories?
foreach (Finder::findFiles('*.txt')->from($dir) as $key => $file) {
// $key is a string containing absolute filename with path
// $file is an instance of SplFileInfo
}
The files in the $file
variable are instances of the SplFileInfo class.
If the directory does not exist, an Nette\UnexpectedValueException
is thrown.
And what about searching for files in a directory without subdirectories? Instead of from()
use
in()
:
Finder::findFiles('*.txt')->in($dir)
Search by multiple masks and even multiple directories at once:
Finder::findFiles('*.txt', '*.php')
->in($dir1, $dir2) // or from($dir1, $dir2)
Parameters can also be arrays:
Finder::findFiles(['*.txt', '*.php'])
->in([$dir1, $dir2]) // or from([$dir1, $dir2])
Depth of search can be limited using the limitDepth()
method.
Searching for Directories
In addition to files, it is possible to search for directories using Finder::findDirectories('subdir*')
.
Or to search for files and directories together using Finder::find('*.txt')
, the mask in this case only applies to
files. When searching recursively with from()
, the subdirectory is returned first, followed by the files in it, which
can be reversed with childFirst()
.
Mask
The mask does not have to describe only the file name, but also the path. Example: searching for *.jpg
files
located in a subdirectory starting with imag
:
Finder::findFiles('imag*/*.jpg')
Thus, the known wildcards *
and ?
represent any characters except the directory separator
/
. The double **
represents any characters, including the directory separator:
Finder::findFiles('imag**/*.jpg')
// finds also image/subdir/file.jpg
In addition you can use in the mask ranges [...]
or negative ranges [!...]
known from regular
expressions. Searching for *.txt
files containing a digit in the name:
Finder::findFiles('*[0-9]*.txt')
Excluding
Use exclude()
to pass masks that the file must not match. Searching for *.txt
files, except those
containing ‚X
‘ in the name:
Finder::findFiles('*.txt')
->exclude('*X*')
If exclude()
is specified after from()
, it applies to crawled subdirectories:
Finder::findFiles('*.php')
->from($dir)
->exclude('temp', '.git')
Filtering
You can also filter the results, for example by file size. Here's how to find files of size between 100 and 200 bytes:
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200)
->from($dir)
Filtering by date of last change. Example: searching for files changed in the last two weeks:
Finder::findFiles('*.php')
->date('>', '- 2 weeks')
->from($dir)
Both functions understand the operators >
, >=
, <
, <=
,
=
, !=
.
Here we traverse PHP files with number of lines greater than 1000. As a filter we use a custom callback:
$hasMoreThan100Lines = function (SplFileInfo $file): bool {
return count(file($file->getPathname())) > 1000;
};
Finder::findFiles('*.php')
->filter($hasMoreThan100Lines)
Handy, right? You will certainly find a use for Finder in your applications.