Finder 4.0: 10 years of experience under the hood

2 years ago by David Grudl  

Nette Finder allows you to search for files and folders based on criteria. The new version 4.0 has been completely rewritten using 10 years of experience using previous versions. This has resulted in a tool that is even easier and more efficient to use.

Masks Everywhere All at Once

The new version of Nette Finder 4.0 supports the ** character called globstar, which is a powerful trump card because it allows you to search even in subdirectories. For example, use the mask src/**/tests/*.php to search for all PHP files in the tests directory located in src or any of its subdirectories:

Finder::findFiles('src/**/tests/*.php');

Masks can also be used in in(), from() or exclude() methods:

Finder::findFiles('*.php')->in('/foo/**/vendor'); // finds /foo/sub1/sub2/vendor/file.php
Finder::findFiles('*.php')->from('/foo/**/vendor'); // finds also /foo/sub1/sub2/vendor/sub3/file.php

FileInfo

The returned files are Nette\Utils\FileInfo objects, a descendant of the original SplFileInfo, which also adds the getRelativePath() and getRelativePathname() methods useful for traversing in depth via from(). As well as the read() and write() methods for reading/writing the contents of a file:

foreach (Finder::findFiles('*.md') as $file) {
	$contents = $file->read();
	$contents = str_replace('http://', 'https://', $contents);
	$file->write($contents);
}

Extended API

Use the files() and directories() methods to add what else to search for. The methods can be called repeatedly, and an array of masks can be provided as a parameter:

Finder::findDirectories('tests') // all directories tests/
	->files(['*.php', '*.phtml']); // plus all PHP files

An alternative to static methods is to create an instance using new Finder (the object created this way does not search for anything) and specify what to search for using files() and directories():

(new Finder)
	->directories()      // all directories
	->files('*.php');    // plus all PHP files

If you need to search for different file types that are in different locations or meet different criteria, use the append() method. It returns a new Finder object, so you can chain method calls:

($finder = new Finder) // store the first Finder in the $finder variable
	->files('*.php')   // in src/ looking for *.php files
	->from('src')
	->append()
	->files('*.md')    // in docs/ we are looking for *.md files larger than 1000 bytes
	->from('docs')
	->size('>', 1000)
	->append()
	->files('*.json'); // looking for *.json files in the current folder

Alternatively, the append() method can be used to add a specific file or array of files:

$finder = Finder::findFiles('*.txt')
	->append(__FILE__);

Sorting of Results

Finder 4.0 offers the possibility to sort results. The sortByName() method sorts the results by file name. The sorting is natural, i.e. it correctly handles numbers in the names and returns e.g. foo1.txt before foo10.txt. The finder also allows you to sort using a custom function. For example, this is how we sort files by size:

$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());

And Much More

For a complete list of features, see the Finder documentation.

The Finder is now part of the Nette Utils 4.0 package. Thus the nette/utils version 4 package replaces the original nette/finder. Notes for the upgrade are in the migration guide.