Recursively counting files with PHP

10,579

Solution 1

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

Solution 2

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

?>

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()

Solution 3

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

Solution 4

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;
}
Share:
10,579
user18359
Author by

user18359

Updated on June 17, 2022

Comments

  • user18359
    user18359 almost 2 years

    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.

  • user18359
    user18359 about 15 years
    Hi. Thanks for the prompt assistance. This script is resulting in a timeout error for me. "Fatal error: Maximum execution time of 30 seconds exceeded". Not sure why. There are only 8 folders and 68 files in the target directory.
  • Paolo Bergantino
    Paolo Bergantino about 15 years
    Try recopy-pasting the one that is currently there. My original answer had an error in it, this one is tested and works.
  • user18359
    user18359 about 15 years
    Much better, thanks! The number isn't quite adding up right though. I added echo "$size $t<br />"; after $size++; in order to debug - it appears that the .DS_Store files are still being counted. Any further advice would be great.
  • user18359
    user18359 about 15 years
    Nevermind - just moved if(in_array... one level up and that did the trick! Thanks again.
  • user18359
    user18359 about 15 years
    This also did the trick after I modified it for the $ignore array. Thanks!
  • NaN
    NaN over 2 years
    This is correct but if there are too many files the script goes incredibly slow.
  • NaN
    NaN over 2 years
    Much faster than IteratorIterator, thank you
  • NaN
    NaN over 2 years
    I tried both this and foreach/foreach and the RecursiveIterator is very slow when there are many files.
  • davidmars
    davidmars over 2 years
    @NaN how many are too many ?
  • NaN
    NaN about 2 years
    It depends on machine speed. Too many is when you see the script lagging when finding files to the list.