I was messing around the other day with creating a multi-dimensional array of file names from recursively searching a given file system path. I tried the RecursiveDirectoryIterator and the RecursiveIteratorIterator from the SPL. While they are both very useful and fairly simple to implement, I needed to keep the multi-dimensional nature of the file system tree intact rather than flatten it out as the SPL recursive iterators tend to do. I also needed a count of the files processed at each level of the array, so each directory would know how many files were in all of it’s subdirectories — without having to foreach through all the dimensions of the array and count() every subarray.

Anyway, the solution was pretty straightforward. Here’s my implementation:

$fileArray = array();
$filePath = '/var/www';
$filter = '#\.(gif|jpe?g|png)$#i';
$fileCount = getFileInfo($filePath, $fileArray, $filter);

function getFileInfo($filePath, &$fileArray, $filter='') {
    $leaves = 0;
    $d = new DirectoryIterator($filePath);
    foreach ( $d as $f ) {
        $name = $f->getFilename();
        if ( substr($name, 0, 1) == '.' )
            continue;
        elseif ( $f->isDir() ) {
            $fileArray[$name] = array();
            $sub_leaves = getFileInfo("$filePath/$name", $fileArray[$name], $filter);
            $fileArray[$name]['fileCount'] = $sub_leaves;
            $leaves += $sub_leaves;
        }
        elseif ( !$filter || preg_match($filter, $name) ) {
            $fileArray[] = $name;
            $leaves++;
        }
    }
    return $leaves;
}

The code above will create a multi-dimensional array ($fileArray) which contains all the directories/files below the given path ($filePath), optionally filtering the file names by the perl regex supplied ($filter). The getFileInfo() function calls itself recursively, creating a new subarray for each directory it finds. Each array in the structure also has a fileCount key which is a count of all the file names in every subarray below it. The function returns a total count of all file names in the structure.

For my application, I wanted to automatically filter any files/directories that started with a dot character and not just the normal ./ and ../ files (e.g. .svn/, .cvs/, various config files, etc…). Your mileage may vary…

Lastly, this function requires PHP 5+ with the Standard PHP Library (SPL) available. The prettified source is available here.