How to ignore directories using RecursiveIteratorIterator?

I tried several methods to ignore specific directories using RecursiveIteratorIterator in the file system.

For example, let's say I want to ignore the following directory: /cache .

My Iterator looks like this:

 //$dirname is root $directory = new RecursiveDirectoryIterator($dirname); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); foreach ($mega as $fileinfo) { echo $fileinfo; } 

I could ignore some file extensions using pathinfo , for example, this works:

 $filetypes = array("jpg", "png"); $filetype = pathinfo($fileinfo, PATHINFO_EXTENSION); foreach ($mega as $fileinfo) { if (!in_array(strtolower($filetype), $filetypes)) { echo $fileinfo; } } 

When I try to use it with PATHINFO_DIRNAME (with the corresponding directory paths in the array), it does not work, there are no errors, it just does not ignore directories.

I also experimented using FilterIterator no avail, and now I think I should use RegexIterator .

What would be the easiest and most efficient way to ignore directories using RecursiveIteratorIterator ?


Experiments that didn’t work. Using PATHINFO_DIRNAME

 $dirignore = array("cache", "cache2"); $directory = new RecursiveDirectoryIterator($dirname); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); $dirtype = pathinfo($fileinfo, PATHINFO_DIRNAME); if (!in_array($dirtype), $dirignore)) { echo $fileinfo; //no worky still echo directories } 

Using FilterIterator (not sure how this works)

 class DirFilter extends FilterIterator { public function accept() { //return parent::current() != "..\cache\"; $file = $this->getInnerIterator()->current(); if ($file != "..\cache") return $file->getFilename(); //also tried with same error as below //return !preg_match('/\cache', $file->getFilename()); } } $directory= new RecursiveDirectoryIterator($dirname); $directory = new DirFilter($directory); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); // loop 

This results in Error: An instance of RecursiveIterator or IteratorAggregate creating it is required

+4
source share
1 answer

Your DirFilter wants to extend the RecursiveFilterIterator , as it is used with a recursive iterator. Not doing this is the cause of your error.

 class DirFilter extends RecursiveFilterIterator { // … } 

The next step is to figure out how to use accept() correctly. It is supposed to return true or false , which determines whether the current element should be included ( true ) or excluded ( false ) from the iteration. Returning the file name from accept() is not what you want to do.

 class DirFilter extends RecursiveFilterIterator { public function accept() { $excludes = array("cache", "cache2"); return !($this->isDir() && in_array($this->getFilename(), $excludes)); } } 

Perhaps it would be nice to go into an array of excluded directories. This requires a bit more code, but much more reusability.

 class DirFilter extends RecursiveFilterIterator { protected $exclude; public function __construct($iterator, array $exclude) { parent::__construct($iterator); $this->exclude = $exclude; } public function accept() { return !($this->isDir() && in_array($this->getFilename(), $this->exclude)); } public function getChildren() { return new DirFilter($this->getInnerIterator()->getChildren(), $this->exclude); } } 

Then this code can be used as:

 $directory = new RecursiveDirectoryIterator($dirname); $filtered = new DirFilter($directory, $dirignore); $mega = new RecursiveIteratorIterator($filtered, …); 
+6
source

Source: https://habr.com/ru/post/1468789/


All Articles