Count files in a directory while excluding others by directory and subdirectories using PHP

249 views Asked by At

I have implemented a file-counting code using a function found here at SO: https://stackoverflow.com/a/640944/2554788.

The function goes thus:

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

It works well, until I want to exclude certain directories and all their contents. What I need is to pass:

$ignore = array('.','..','cgi-bin','.DS_Store', 'SPECIAL_DIR');

At the moment, this function omits "SPECIAL_DIR", but seems to count all its content files, since they do not textually match "SPECIAL_DIR"!

I've bumped into a couple of solutions here and elsewhere that are meant to exclude files by path, but I haven't found one focused on recursively counting files (not listing them or anything else).

Thanks all.

1

There are 1 answers

0
Ifedi Okonkwo On

I came across this from the user-contributed section in PHP Manual. Credit to carneiro at isharelife dot com dot br

function directoryToArray($directory, $recursive = true, $listDirs = false, $listFiles = true, $exclude = '') {
         $arrayItems = array();
         $skipByExclude = false;
         $handle = opendir($directory);
         if ($handle) {
             while (false !== ($file = readdir($handle))) {
             preg_match("/(^(([\.]){1,2})$|(\.(svn|git|md))|(Thumbs\.db|\.DS_STORE))$/iu", $file, $skip);
             if($exclude){
                 preg_match($exclude, $file, $skipByExclude);
             }
             if (!$skip && !$skipByExclude) {
                 if (is_dir($directory. '/' . $file)) {
                     if($recursive) {
                         $arrayItems = array_merge($arrayItems, directoryToArray($directory. '/' . $file, $recursive, $listDirs, $listFiles, $exclude));
                     }
                     if($listDirs){
                         $file = $directory . '/' . $file;
                         $arrayItems[] = $file;
                     }
                 } else {
                     if($listFiles){
                         $file = $directory . '/' . $file;
                         $arrayItems[] = $file;
                     }
                 }
             }
         }
         closedir($handle);
         }
         return $arrayItems;
  }

The function returns complete path listings. Exclusion is by regex passed into the function, and the file count comes from count()ing the returned array.

This seems to do the job, but I await any alternative answer on this, regarding stuff like code brevity and performance.