Могу ли я заставить RecursiveDirectoryIterator пропускать нечитаемые каталоги?

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

Есть ли способ для этого кода не генерировать исключение UnexpectedValueException "не удалось открыть dir: Permission denied" всякий раз, когда внутри каталога, который я пытаюсь перечислить, находится нечитаемый подкаталог?

ОБНОВИТЬ

преобразование foreach() в while() и явно вызывая Iterator::next() завернут в try() catch {} не помогает Этот код:

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

бесконечный цикл, если есть нечитаемый подкаталог.

3 ответа

Решение

Видимо, вы можете пройти $flags параметр для конструктора. В документах только один флаг, но он делает именно то, что вы хотите: catches exceptions during getChildren() calls and simply jumps to the next element,

Измените свой код создания класса на

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

и это должно работать

Вы могли бы сделать что-то вроде этого:

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";
}

Возможно, что позиция итератора все еще будет действительной, даже если каталог не читается.

Вы можете проверить состояние записи каталога. Небрежный непроверенный пример кода:

$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("."));
foreach ($iter as $dir) {
    if($dir->isReadable()){
        //do something
    }
}
Другие вопросы по тегам