【问题标题】:Recursively counting files with PHP使用 PHP 递归计数文件
【发布时间】:2021-11-11 01:43:00
【问题描述】:

一个新手的简单问题,我的 Google-Fu 让我失望了。使用 PHP,您如何计算给定目录中的文件数,包括任何子目录(以及它们可能拥有的任何子目录等)?例如如果目录结构如下所示:

/Dir_A/ /Dir_A/File1.blah /Dir_A/Dir_B/ /Dir_A/Dir_B/File2.blah /Dir_A/Dir_B/File3.blah /Dir_A/Dir_B/Dir_C/ /Dir_A/Dir_B/Dir_C/File4.blah /Dir_A/Dir_D/ /Dir_A/Dir_D/File5.blah

脚本应返回“./Dir_A”的“5”。

我拼凑了以下内容,但并没有完全返回正确答案,我不确定为什么:

函数 getFilecount($path = '.', $filecount = 0, $total = 0){ $ignore = array('cgi-bin', '.', '..', '.DS_Store' ); $dh = @opendir( $path ); 而(假!==($file=readdir($dh))){ if( !in_array( $file, $ignore ) ){ if(is_dir("$path/$file")){ $filecount = count(glob("$path/$file/" . "*")); $total += $filecount; 回声$文件计数; /* 调试 */ 回声“$总计”; /* 调试 */ echo "$path/$file
"; /* 调试 */ getFilecount("$path/$file", $filecount, $total); } } } 返回$总计; }

非常感谢任何帮助。

【问题讨论】:

    标签: php recursion count


    【解决方案1】:

    这应该可以解决问题:

    function getFileCount($path) {
        $size = 0;
        $ignore = array('.','..','cgi-bin','.DS_Store');
        $files = scandir($path);
        foreach($files as $t) {
            if(in_array($t, $ignore)) continue;
            if (is_dir(rtrim($path, '/') . '/' . $t)) {
                $size += getFileCount(rtrim($path, '/') . '/' . $t);
            } else {
                $size++;
            }   
        }
        return $size;
    }
    

    【讨论】:

    • 嗨。感谢您的及时帮助。该脚本导致我出现超时错误。 “致命错误:超过 30 秒的最大执行时间”。不知道为什么。目标目录下只有8个文件夹和68个文件。
    • 尝试重新复制粘贴当前存在的那个。我原来的答案有一个错误,这个已经过测试并且有效。
    • 好多了,谢谢!不过,这个数字加起来并不完全正确。我添加了 echo "$size $t
      ";在 $size++ 之后;为了调试 - 似乎仍在计算 .DS_Store 文件。任何进一步的建议都会很棒。
    • 没关系 - 只是将 if(in_array... 移动了一级,就成功了!再次感谢。
    • 比IteratorIterator快很多,谢谢
    【解决方案2】:

    使用 SPL,然后查看是否仍然出现错误。

    RecursiveDirectoryIterator

    使用示例:

    <?php
    
    $path = realpath('/etc');
    
    $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
    foreach($objects as $name => $object){
        echo "$name\n";
    }
    
    ?>
    

    这将打印 $path 下的所有文件和目录的列表(包括 $path ifself)。如果要省略目录,请删除 RecursiveIteratorIterator::SELF_FIRST 部分。

    然后只需使用 isDir()

    【讨论】:

    • 在我为 $ignore 数组修改它之后,这也起到了作用。谢谢!
    • 这个和foreach/foreach我都试过了,当文件很多时RecursiveIterator很慢。
    【解决方案3】:

    根据安德鲁的回答...

        $path = realpath('my-big/directory');
        $objects = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($path),
            RecursiveIteratorIterator::SELF_FIRST
        );
        $count=iterator_count($objects);
        echo number_format($count); //680,642 wooohaah!
    

    这样我就可以计算(不列出)数千个文件。 680,642 个文件实际上不到 4.6 秒 ;)

    【讨论】:

    • 这是正确的,但是如果文件太多,脚本会变得非常慢。
    【解决方案4】:

    Paolo Bergantino 几乎可以使用他的代码,但该函数仍会计算 .DS_Store 文件,因为他拼写错误。下面的正确代码

    function getFileCount($path) {
        $size = 0;
        $ignore = array('.','..','cgi-bin','.DS_Store');
        $files = scandir($path);
        foreach($files as $t) {
            if(in_array($t, $ignore)) continue;
            if (is_dir(rtrim($path, '/') . '/' . $t)) {
                $size += getFileCount(rtrim($path, '/') . '/' . $t);
            } else {
                $size++;
            }   
        }
        return $size;
    }
    

    【讨论】:

      【解决方案5】:

      你为什么要传递 $filecount? [passed-in] 值没有被使用;唯一的用法是在 "$total += $filecount" 处,并且您在此之前覆盖了 $filecount。

      你错过了函数遇到常规(非目录)文件的情况。

      编辑:我刚刚注意到对 glob() 的调用。这不是必需的。无论如何,您的函数正在递归地触及整个目录树中的每个文件。请参阅@Paolo Bergantino 的回答。

      【讨论】:

        【解决方案6】:

        查看glob()函数的PHP手册:http://php.net/glob

        它在 cmets 中有关于如何使其递归的示例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-08-28
          • 1970-01-01
          • 2010-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多