我可以让RecursiveDirectoryIterator跳过不可读的目录吗?

时间:2022-12-28 20:47:20
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?

有没有办法让这个代码不会抛出UnexpectedValueException“无法打开目录:权限被拒绝”只要目录中有一个不可读的子目录我尝试列出?

UPDATE

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

将foreach()转换为while()并显式调用try()catch {}中包含的Iterator :: next()没有帮助。这段代码:

$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.

如果存在不可读的子目录,则是无限循环。

3 个解决方案

#1


19  

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.

显然你可以将$ flags参数传递给构造函数。文档中只有一个标志,但它完全符合您的要求:在getChildren()调用期间捕获异常并简单地跳转到下一个元素。

Change your class creation code to

将您的类创建代码更改为

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

and it should work

它应该工作

#2


7  

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

#3


-1  

It's possible that the iterator position will still be valid even if a directory is not readable.

即使目录不可读,迭代器位置仍可能有效。

You could check the state of the directory entry. Sloppy untested sample code:

您可以检查目录条目的状态。邋un的未经测试的示例代码:

$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("."));
foreach ($iter as $dir) {
    if($dir->isReadable()){
        //do something
    }
}

#1


19  

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.

显然你可以将$ flags参数传递给构造函数。文档中只有一个标志,但它完全符合您的要求:在getChildren()调用期间捕获异常并简单地跳转到下一个元素。

Change your class creation code to

将您的类创建代码更改为

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

and it should work

它应该工作

#2


7  

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

#3


-1  

It's possible that the iterator position will still be valid even if a directory is not readable.

即使目录不可读,迭代器位置仍可能有效。

You could check the state of the directory entry. Sloppy untested sample code:

您可以检查目录条目的状态。邋un的未经测试的示例代码:

$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("."));
foreach ($iter as $dir) {
    if($dir->isReadable()){
        //do something
    }
}