Recursive Directories Into Multi-dimensional Array
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.
Filed in PHP, Technology 2 Comments so far
mercerd on 17 Jul 2009 at 12:00 pm #
interesting material, where such topics do you find? I will often go
DProphet on 17 Jul 2009 at 9:48 pm #
Hi… thanks for the interest. This is just something I needed for an application I was working on. Here are links to the Standard PHP Library (SPL) iterators I was mentioning:
http://us3.php.net/manual/en/class.directoryiterator.php
http://us3.php.net/manual/en/class.recursivedirectoryiterator.php
http://us3.php.net/manual/en/class.recursiveiteratoriterator.php
Unfortunately, there’s not a lot of info in the PHP manual, yet, about the SPL. So, you have to experiment…
EDIT: I’ve also fixed a few bugs in the code above. I was missing a $ on one of the $sub_leaves variables and I wasn’t passing the $filter variable to the recursive calls to getFileInfo(). The code above has been tested and works on versions of PHP that include the SPL.