Kiksy
Kiksy

Reputation: 1292

PHP Recursive Directory Iterator - ignore certain files.

I have a recursive directory iterator to select files from within a directory. SKIP_DOTS allows me to ignore the '.' and '..' elements, but I'd like to be able to also ignore '__MACOSX' directory and another other hidden files such as '.cache.php'

$iterator = new RecursiveDirectoryIterator($directory);
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
$all_files  = new RecursiveIteratorIterator($iterator); 

There are other answers here and here but just wondered if there was a cleaner way?

I was hoping there was going to be something in PHP Manual - FilesystemIterator SetFlags but it seems not.

Upvotes: 8

Views: 8174

Answers (3)

Zombo
Zombo

Reputation: 1

To filter other items, you can utilize RecursiveCallbackFilterIterator. This is nice because with folders that hit the filter, the entire subpath is pruned. Here is an example filtering a file and subfolder:

<?php

$f_filter = function ($o_info) {
   $s_file = $o_info->getFilename();
   if ($s_file == '.git') {
      return false;
   }
   if ($s_file == 'readme.md') {
      return false;
   }
   return true;
};

$o_dir = new RecursiveDirectoryIterator('.');
$o_filter = new RecursiveCallbackFilterIterator($o_dir, $f_filter);
$o_iter = new RecursiveIteratorIterator($o_filter);

foreach ($o_iter as $o_info) {
   echo $o_info->getPathname(), "\n";
}

https://php.net/class.recursivecallbackfilteriterator

Upvotes: 1

Kiksy
Kiksy

Reputation: 1292

Thanks to @Sven and the PHP Docs:

$iterator = new RecursiveDirectoryIterator($directory);
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);

$filter = new MyRecursiveFilterIterator($iterator);

$all_files  = new RecursiveIteratorIterator($filter,RecursiveIteratorIterator::SELF_FIRST);

Then extended RecursiveFilterIterator

class MyRecursiveFilterIterator extends RecursiveFilterIterator {

    public static $FILTERS = array(
        '__MACOSX',
    );

    public function accept() {
        return !in_array(
            $this->current()->getFilename(),
            self::$FILTERS,
            true
        );
    }

}

As per the comment In the PHP Manual

Upvotes: 11

Sven
Sven

Reputation: 70933

Add a filter layer between RecursiveIteratorIterator and RecursiveDirectoryIterator: Create a RecursiveFilterIterator and code the accept() function that returns true if you want the element to be in the result. Put the directory iterator into the filter iterator, put the filter iterator in the RecursiveIteratorIterator. Iterate.

There is no predefined SKIP constant for such special cases as "__MACOSX" directories.

Upvotes: 1

Related Questions