Php 无法使用RecursiveDirectoryIterator跳过不可读的目录

Php 无法使用RecursiveDirectoryIterator跳过不可读的目录,php,directory,directory-walk,Php,Directory,Directory Walk,我想获得所有子目录的列表,我下面的代码可以工作,除非我对某些文件夹拥有只读权限 在下面的问题中,它展示了如何使用RecursiveDirectoryIterator跳过目录 然而,我的代码在这里略有不同,我无法回避这个问题 $path = 'www/'; foreach (new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PAT

我想获得所有子目录的列表,我下面的代码可以工作,除非我对某些文件夹拥有只读权限

在下面的问题中,它展示了如何使用RecursiveDirectoryIterator跳过目录 然而,我的代码在这里略有不同,我无法回避这个问题

$path = 'www/';
foreach (new RecursiveIteratorIterator(
       new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME),
            RecursiveIteratorIterator::CHILD_FIRST) as $file => $info) 
            {
                if ($info->isDir())
                {
                       echo $file . '<br>';                     
                }
            }   
我试着用另一个问题中被接受的答案来代替它

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

但是,这段代码不会像我希望的那样给我一个www内所有目录的列表,我在这里哪里出错了?

该函数自动跳过读取错误,并且应该简化您的代码。

如果您遇到未经处理的异常,为什么不将该代码放在一个try块中,在无法读取目录时使用异常捕获块捕获错误?通过查看您的代码和问题,给出一个简单的建议。在PHP中可能有一种更简洁的方法

我已经设置了以下目录结构:

/
    test.php <-- the test script
    www/
        test1/ <-- permissions = 000
            file1
        test2/
            file2
        file3
它的输出如下:

Array
(
    [www/test2/file2] => SplFileInfo Object
        (
            [pathName:SplFileInfo:private] => www/test2/file2
            [fileName:SplFileInfo:private] => file2
        )

    [www/file3] => SplFileInfo Object
        (
            [pathName:SplFileInfo:private] => www/file3
            [fileName:SplFileInfo:private] => file3
        )

)
这正如预期的那样有效

更新

添加了您在原始示例中使用的标志(尽管我认为这些是默认的):


如果要返回不可读的目录名,需要先使用
SELF\u
常量。 当您首先执行
CHILD_
时,它试图进入目录,但失败,当前目录名不包括在内

$path = 'testing';

$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);

$iterator = new RecursiveIteratorIterator($directory_iterator,
    RecursiveIteratorIterator::SELF_FIRST,
    RecursiveIteratorIterator::CATCH_GET_CHILD);

foreach ($iterator as $file => $info) {
    if ($info->isDir()) {
        echo $file . "\n";
    }
}

导言

代码的主要问题是先使用
CHILD\u

可选模式。可能的值是

  • 递归迭代器::仅保留默认值。只列出迭代中的叶子
  • RecursiveIteratorIterator::SELF_FIRST-列出迭代中的叶子和父母,父母排在第一位
  • RecursiveIteratorIterator::CHILD_FIRST-列出迭代中的叶子和父母,叶子排在第一位
您应该首先使用
SELF\u
,以便包含当前目录。您还忘记添加可选参数
recursiveiterator::CATCH\u GET\u CHILD

可选标志。可能的值是RecursiveIteratorIterator::CATCH_GET_CHILD,它将忽略调用RecursiveIteratorIterator::getChildren()时抛出的异常

重新访问您的代码

foreach (new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME),
        RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD) as $file => $info)
{
    if ($info->isDir())
    {
        echo $file . '<br>';
    }
}
使用的类

class ReadableDirectoryIterator extends RecursiveFilterIterator {
    function __construct($path) {
        if (!$path instanceof RecursiveDirectoryIterator) {
            if (! is_readable($path) || ! is_dir($path))
                throw new InvalidArgumentException("$path is not a valid directory or not readable");
            $path = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
        }
        parent::__construct($path);
    }

    public function accept() {
        return $this->current()->isReadable() && $this->current()->isDir();
    }
}

不如尝试捕获意外的ValueException。也许你甚至可以检查该错误的唯一异常代码。否则,您可以解析“权限被拒绝”的异常消息

我建议检查一下

此代码100%有效

您只需使用此功能即可扫描所需目录或驱动器中的文件和文件夹。您只需要将所需目录的路径传递到函数中。该函数的第二个参数是显示扫描文件和文件夹的完整路径。第二个参数的值为False表示不显示完整路径

数组$ignore用于从列表中排除任何所需的文件名或文件夹名

函数返回包含文件和文件夹列表的数组

此函数跳过递归时无法读取的文件和文件夹。


<?php
    $path = "D:/Movies";

    $directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);

    $files = new RecursiveIteratorIterator($directory_iterator,
            RecursiveIteratorIterator::SELF_FIRST,
            RecursiveIteratorIterator::CATCH_GET_CHILD);

    try {
        foreach( $files as $fullFileName => $file) {
            $path_parts = pathinfo($fullFileName);

            if(is_file($fullFileName)){
                $path_parts = pathinfo($fullFileName);
                $fileName[] =  $path_parts['filename'];
                $extensionName[] =  $path_parts['extension'];
                $dirName[] =  $path_parts['dirname'];
                $baseName[] =  $path_parts['basename'];
                $fullpath[] = $fullFileName;
            }
        }


        foreach ($fullpath as $filles){
                echo $filles;
                echo "</br>";
        }

    }
    catch (UnexpectedValueException $e) {
        printf("Directory [%s] contained a directory we can not recurse into", $directory);
    }
?>

如果它没有返回www中的所有目录,它会返回什么?它会返回目录,直到它得到一个它没有读取权限的目录,然后我得到错误,我希望能够跳过那些受限文件夹并返回目录中的所有其他文件夹。我确实查看了这些文件夹,谢谢,但无法获取www的子目录?您应该能够通过将glob pattern设置为
***
来获取子目录。谢谢,这给了我一个数组中的结果,我需要进一步阅读迭代器\u to \u数组当我尝试将您的代码片段放入数组时,它会运行代码,但在初始测试时不会给出任何结果。@ak85当您以独立代码运行我的答案时会发生什么情况?我得到了数组,正如您所描述的,跳过了安全文件夹,但到目前为止,我无法将您的代码转换为我在示例。@ak85我已经更新了我的答案,以模仿您在问题开始时的回答;看看这对你是否有效。这看起来不错,我现在不在我的测试环境中,明天将确认。这段代码似乎生成了我所追求的格式folders@ak85肯定会的。。我只在第二个示例中添加了一个装饰器。。。而且效果很好。
$path = 'testing';

$directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);

$iterator = new RecursiveIteratorIterator($directory_iterator,
    RecursiveIteratorIterator::SELF_FIRST,
    RecursiveIteratorIterator::CATCH_GET_CHILD);

foreach ($iterator as $file => $info) {
    if ($info->isDir()) {
        echo $file . "\n";
    }
}
foreach (new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($path,RecursiveDirectoryIterator::KEY_AS_PATHNAME),
        RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD) as $file => $info)
{
    if ($info->isDir())
    {
        echo $file . '<br>';
    }
}
foreach ( new RecursiveIteratorIterator(
        new ReadableDirectoryIterator($path),RecursiveIteratorIterator::CHILD_FIRST) as $file ) {
    echo $file . '<br>';
}
class ReadableDirectoryIterator extends RecursiveFilterIterator {
    function __construct($path) {
        if (!$path instanceof RecursiveDirectoryIterator) {
            if (! is_readable($path) || ! is_dir($path))
                throw new InvalidArgumentException("$path is not a valid directory or not readable");
            $path = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
        }
        parent::__construct($path);
    }

    public function accept() {
        return $this->current()->isReadable() && $this->current()->isDir();
    }
}
function dirScan($dir, $fullpath = false){

    $ignore = array(".","..");
    if (isset($dir) && is_readable($dir)){
        $dlist = array();
        $dir = realpath($dir);
        $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir,RecursiveDirectoryIterator::KEY_AS_PATHNAME),RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);

        foreach($objects as $entry){    
                    if(!in_array(basename($entry), $ignore)){
                        if (!$fullpath){
                            $entry = str_replace($dir, '', $entry);
                        }           
                            $dlist[] = $entry;
                    }                        
        }       
        return $dlist;
    }

}
<?php
    $path = "D:/Movies";

    $directory_iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);

    $files = new RecursiveIteratorIterator($directory_iterator,
            RecursiveIteratorIterator::SELF_FIRST,
            RecursiveIteratorIterator::CATCH_GET_CHILD);

    try {
        foreach( $files as $fullFileName => $file) {
            $path_parts = pathinfo($fullFileName);

            if(is_file($fullFileName)){
                $path_parts = pathinfo($fullFileName);
                $fileName[] =  $path_parts['filename'];
                $extensionName[] =  $path_parts['extension'];
                $dirName[] =  $path_parts['dirname'];
                $baseName[] =  $path_parts['basename'];
                $fullpath[] = $fullFileName;
            }
        }


        foreach ($fullpath as $filles){
                echo $filles;
                echo "</br>";
        }

    }
    catch (UnexpectedValueException $e) {
        printf("Directory [%s] contained a directory we can not recurse into", $directory);
    }
?>