使用PHP递归计数文件

问题描述:

Simple question for a newb and my Google-Fu is failing me. Using PHP, how can you count the number of files in a given directory, including any sub-directories (and any sub-directories they might have, etc.)? e.g. if directory structure looks like this:

/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

The script should return with '5' for "./Dir_A".

I've cobbled together the following but it's not quite returning the correct answer, and I'm not sure why:

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

I'd greatly appreciate any help.

对于newb和我的Google-Fu的简单问题让我失望。 使用PHP,如何计算给定目录中的文件数,包括任何子目录(以及它们可能具有的任何子目录等)? 例如 如果目录结构如下所示: p>

 
 / 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 
   pre> 
 
 

脚本应该返回“5”表示“./Dir_A".

nnn

我拼凑了以下内容,但它并没有完全回复正确的答案 ,我不确定原因: p>

 
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); } } } 返回$ total; } pre>

我非常感谢您的帮助。 p> div>

This should do the trick:

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

Why are you passing $filecount? The [passed-in] value is not being used; the only usage is at "$total += $filecount" and you're overriding $filecount just before that.

You're missing the case when the function encounters a regular (non-dir) file.

Edit: I just noticed the call to glob(). It's not necessary. Your function is recursively touching every file in the whole directory tree, anyway. See @Paolo Bergantino's answer.

Use the SPL, then see if you still get an error.

RecursiveDirectoryIterator

Usage example:

<?php

$path = realpath('/etc');

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

?>

This prints a list of all files and directories under $path (including $path ifself). If you want to omit directories, remove the RecursiveIteratorIterator::SELF_FIRST part.

Then just use isDir()

Check the PHP manual on glob() function: http://php.net/glob

It has examples in comments as to how to make it recursive.

Paolo Bergantino was almost with his code, but the function will still count .DS_Store files since he misspelled it. Correct Code below

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

based on Andrew's answer...

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

like that i'm able to count (not listing) thousands & thousands files. 680,642 files in less than 4.6 seconds actually ;)