用PHP递归计算文件数

用PHP递归计算文件数,php,recursion,count,Php,Recursion,Count,对于一个新手和我的谷歌Fu来说,一个简单的问题让我失望。使用PHP,如何计算给定目录中的文件数,包括任何子目录(以及它们可能拥有的任何子目录,等等)?e、 g.如果目录结构如下所示: /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

对于一个新手和我的谷歌Fu来说,一个简单的问题让我失望。使用PHP,如何计算给定目录中的文件数,包括任何子目录(以及它们可能拥有的任何子目录,等等)?e、 g.如果目录结构如下所示:

/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 /董事A/ /目录A/File1.blah /目录A/目录B/ /目录A/目录B/文件2.blah /目录A/目录B/文件3.blah /目录A/目录B/目录C/ /目录A/目录B/目录C/文件4.blah /目录A/目录D/ /Dir_A/Dir_D/File5.blah 脚本应返回“/Dir_A”的“5”

我已经拼凑了以下内容,但并没有返回正确答案,我也不确定原因:

function getFilecount( $path = '.', $filecount = 0, $total = 0 ){ $ignore = array( 'cgi-bin', '.', '..', '.DS_Store' ); $dh = @opendir( $path ); while( false !== ( $file = readdir( $dh ) ) ){ if( !in_array( $file, $ignore ) ){ if( is_dir( "$path/$file" ) ){ $filecount = count(glob( "$path/$file/" . "*")); $total += $filecount; echo $filecount; /* debugging */ echo " $total"; /* debugging */ echo " $path/$file
"; /* debugging */ getFilecount( "$path/$file", $filecount, $total); } } } return $total; } 函数getFilecount($path='.',$filecount=0,$total=0){ $ignore=array('cgi-bin'、'.'、'...'、'.DS_-Store'); $dh=@opendir($path); while(false!==($file=readdir($dh)){ 如果(!in_数组($file,$ignore)){ 如果(is_dir(“$path/$file”){ $filecount=count(全局(“$path/$file/”*”); $total+=$filecount; echo$filecount;/*调试*/ echo“$total”/*调试*/ echo“$path/$file
”;/*调试*/ getFilecount(“$path/$file”,$filecount,$total); } } } 返回$total; }
非常感谢您的帮助。

您为什么要传递$filecount?未使用[传入]值;唯一的用法是“$total+=$filecount”,而在此之前您正在覆盖$filecount

当函数遇到一个常规(非dir)文件时,您将错过这种情况


编辑:我刚刚注意到对glob()的调用。没必要。无论如何,您的函数递归地处理整个目录树中的每个文件。请参阅@Paolo Bergantino的答案。

这应该可以做到:

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

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

用法示例:

<?php

$path = realpath('/etc');

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
    echo "$name\n";
}

?>

这将打印$path(包括$path ifself)下所有文件和目录的列表。如果要省略目录,请删除递归迭代器::SELF_第一部分


然后只需使用isDir()

检查
glob()函数的PHP手册:


它在注释中有一些示例,说明如何使其递归。

保罗·贝甘蒂诺(Paolo Bergantino)几乎完全理解了他的代码,但由于他拼写错误,该函数仍将计算.DS_存储文件的数量。下面是正确的代码

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

根据安德鲁的回答

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

这样我就可以数到(不列出)数千个&数千个文件。680642个文件,实际时间不到4.6秒;)

嗨。谢谢你的及时帮助。此脚本导致我出现超时错误。“致命错误:超过30秒的最长执行时间”。不知道为什么。目标目录中只有8个文件夹和68个文件。请尝试重新复制粘贴当前所在的文件夹和文件。我原来的答案有一个错误,这一个是测试和工程。好多了,谢谢!不过,这个数字加起来并不正确。我添加了echo“$size$t
”;$size++之后;为了调试-似乎仍在统计.DS_存储文件。任何进一步的建议都是非常好的。无需担心-只要移动if(在_数组中…一个级别,这就成功了!再次感谢。在我为$ignore数组修改它之后,这也成功了。谢谢!