15
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(".")) as $file) {
  echo "$file\n";
}

Is there any way for this code to not throw UnexpectedValueException "failed to open dir: Permission denied" whenever there is a unreadable subdirectory inside directory I attempt to list?

UPDATE

Converting foreach() to while() and explicitly calling Iterator::next() wrapped in try() catch {} doesn't help. This code:

$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("."));
while($iter->valid()) {
    $file = $iter->current();
    echo "$file\n";
    try {
        $iter->next();
    } catch(UnexpectedValueException $e) {
    }
};

is an infinite loop if there is unreadable subdirectory.

Kamil Szot
  • 15,477
  • 6
  • 53
  • 62
  • wrap it into try catch blocks. and it seems to be a bad ideea to create new objects right inside foreach parentheses – s3v3n Dec 28 '10 at 16:34
  • To Elaborate on s3v3n's comment. It seems to be a bad idea, because what exactly is going on is very hard to determine. Good code isn't always the smallest or fastest code. – DampeS8N Dec 28 '10 at 16:38
  • It's not hard to determine what happens if you know what is RecursiveIteratorIterator and RecursiveDirectoryIterator and what is their common use case. It's simple code. – Kamil Szot Dec 28 '10 at 16:48
  • @s3v3n You gave me an idea of transforming foreach into while and explicitely calling iterator next() inside try {} catch. Unfortunately it doesn't work. – Kamil Szot Dec 28 '10 at 16:58

2 Answers2

24

Apparently you can pass $flags parameter to constructor. There's only one flag in the docs, but it does exactly what you want: catches exceptions during getChildren() calls and simply jumps to the next element.

Change your class creation code to

new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator("."), 
    RecursiveIteratorIterator::LEAVES_ONLY,
    RecursiveIteratorIterator::CATCH_GET_CHILD);

and it should work

German Rumm
  • 5,604
  • 1
  • 22
  • 30
  • That's exactly what I needed. Thank you very much! – Kamil Szot Dec 28 '10 at 22:57
  • I have a similar problem asked here http://stackoverflow.com/questions/14410899/unable-to-skip-unreadable-directories-with-recursivedirectoryiterator do you have any ideas on how I can rework you solution to solve my problem? – ak85 Jan 19 '13 at 22:09
  • Specifically, the flag is: CATCH_GET_CHILD –  Mar 28 '13 at 17:01
8

You could do something like this :

class ReadableFilter extends RecursiveFilterIterator{
    public function accept(){
            return $this->current()->isReadable();
    }
}

$filteredIterator = new RecursiveIteratorIterator(new ReadableFilter(new RecursiveDirectoryIterator(".")));

foreach ($filteredIterator as $file){
    echo "$file\n";
}
rechtstaad
  • 81
  • 1