4

I'm having a directory with this structure :

  • main/
    • |- images/
      • |-- file1.jpg
      • |-- file2.jpg
      • |-- file3.jpg
    • |- documents/
      • |-- private/
        • |--- blahblahblah.docx
      • |-- test.doc
      • |-- test.xls
      • |-- test.txt

I can create a function to complete the work but the RecursiveDirectoryIterator class is much faster and less memory usage this time. How can I use RecursiveDirectoryIterator to list these directory into an array like this :

 array(  
    "main/" => array(  
        "images/" => array(  
            "file1.jpg",   
            "file2.jpg",   
            "file3.jpg"  
        ),   
        "documents/" => array(  
            "private/" => array(  
                "blahblahblah.docx"  
            ),  
            "test.doc",   
            "test.xls",   
            "test.txt"  
        )  
    )  
)  
Gordon
  • 312,688
  • 75
  • 539
  • 559
user366124
  • 67
  • 2
  • 6
  • Out of curiosity, why do you actually want to transform to a *nested* array? What do you intend to do with that array that you cannot do by iterating over the directories alone? – Gordon Aug 24 '10 at 14:55
  • I just want to transform information of a directory to a nested array :) – user366124 Aug 24 '10 at 16:06
  • Yes, but to what purpose? What will you do with the array once you have it? If you are not doing anything with it, it's pointless asking for it. The reason I am asking is because you might be able to skip the multi-dim array if it's just an intermediate format and go to what you intend to do with the array directly from the Iterator. – Gordon Aug 24 '10 at 16:26
  • 1
    @Gordon the purpose I can think of (and is in fact why I searched for this just now) is that I'd like to turn this into JSON output because that's how I'm hooking into my UI. ANd in PHP I'm used to using json_encode() with arrays to get that going. – tim Jan 19 '13 at 00:27
  • Look at this one: http://stackoverflow.com/questions/8479543/php-how-to-populate-a-directory-structure-in-an-array The accepted answer in that thread works exactly the way the OP requested. – tim Jan 19 '13 at 00:36
  • here are some urls mentioned how to work with your problem [http://blogs.techrepublic.com.com/programming-and-development/?p=417](http://blogs.techrepublic.com.com/programming-and-development/?p=417) [http://www.builderau.com.au/program/php/soa/How-do-I-recursively-scan-directories-with-PHP-s-DirectoryIterators-/0,339028448,339289935,00.htm](http://www.builderau.com.au/program/php/soa/How-do-I-recursively-scan-directories-with-PHP-s-DirectoryIterators-/0,339028448,339289935,00.htm) – srinivas Aug 24 '10 at 13:27
  • http://www.php.net/~helly/php/ext/spl/directorytreeiterator_8inc-source.html This source code from your links may solve my problem but I don't know how to apply it? Can you give me an example of it usage please? – user366124 Aug 24 '10 at 13:39

2 Answers2

12

Well, to recursively iterate over the RecursiveIterator, you need a RecursiveIteratorIterator (I know it seems redundant, but it's not)...

However, for your particular case (Where you're looking to generate a structure rather than just visit all of the nodes), I think regular recursion would be better suited...

function DirectoryIteratorToArray(DirectoryIterator $it) {
    $result = array();
    foreach ($it as $key => $child) {
        if ($child->isDot()) {
            continue;
        }
        $name = $child->getBasename();
        if ($child->isDir()) {
            $subit = new DirectoryIterator($child->getPathname());
            $result[$name] = DirectoryIteratorToArray($subit);
        } else {
            $result[] = $name;
        }
    }
    return $result;
}

Edit it to work with non-recursive-iterators...

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
  • I have tried your code but it resulted in a fatal error :( "Call to undefined method SplFileInfo::hasChildren()" – user366124 Aug 24 '10 at 13:40
  • Thanks but now it gives me another error : Maximum function nesting level of '100' reached, aborting! :( – user366124 Aug 24 '10 at 15:17
  • @user366124 Ahh, I forgot to check for the `dot` directories. I'll edit the answer again... – ircmaxell Aug 24 '10 at 15:27
  • Ahh, now it works just fine. However, I realize that the way of using SPL is not always faster ( and many other times maybe even slower ) than creating an user-defined function. Anyway, thanks so much for your help :) – user366124 Aug 24 '10 at 16:03
  • I like it better if you have $i which counts up if its a file. (So have `$i = 0` outside the foreach and replace `$result[]` with `$result[$i]`) – paskl Aug 13 '14 at 14:01
0

Just to record for others, I've turned into a gist a class (RecursiveDirectoryIterator) that can read a directory with all its children and output a JSON or just an array.

https://gist.github.com/jonataswalker/3c0c6b26eabb2e36bc90

And a tree viewer of the output

http://codebeautify.org/jsonviewer/067c13

Jonatas Walker
  • 13,583
  • 5
  • 53
  • 82
  • It would be better if you add a filter for maximum depth and maximum number of files per directory. – ENSATE Sep 29 '22 at 01:09