Traversing directories

A few days ago, I came across a situation where I needed to traverse a multi-level directory structure and operate on all the files.

This can be a bit of a tedious job, as you have to deal with either recursion (nice) or a stack (nicer). I had a feeling there might be something in SPL to take on this task, so I took a peek and ended up with this gem:

  1. <?php
  2. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'));
  3.  
  4. foreach($files as $file) {
  5.  
  6. // Do your stuff here, $file is an SplFileInfo object
  7.  
  8. }
  9.  
  10. ?>

So how does this work?

I'm going to assume you already know what an Iterator is, if not.. search the interweb.

The DirectoryIterator class can be used to traverse directories, much like scandir() does. The RecursiveDirectoryIterator works the same way, except it implements the hasChildren() and getChildren() methods. hasChildren returns true if the current item has sub-items (in this case, if the item is a directory) and getChildren will return a new iterator for the current subdirectory.

Using this system, we would still need some recursive function to actually go and loop through each subdirectory, this is where RecursiveIteratorIterator comes in. If you pass the RecursiveIteratorIterator any RecursiveIterator object (like RecursiveDirectoryIterator), it will traverse the entire tree for you and pass you all the leaf-nodes.

The leaf nodes are in this context the files. If you also want to make directories part of the traversal, you can change this by passing the constant RecursiveIteratorIterator::SELF_FIRST as the mode parameter.

  1. <?php
  2. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'),RecursiveIteratorIterator::SELF_FIRST);
  3. ?>

3 Responses to Traversing directories

  1. 528 andris 2008-02-15 7:19 am

    See more "gems" at http://cvs.php.net/viewvc.cgi/php-src/ext/spl/examples/

  2. 529 sapphirecat 2008-02-15 12:14 pm

    If you need to know the path to a file relative to the root directory passed to the RecursiveDirectoryIterator, pass 0 as the flags argument to RDI's constructor. This will give you an RDI instance inside the loop, which has getSubPathname and getSubPath methods in addition to all the SplFileInfo methods.

    $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root, 0));

  3. 533 Anti Veeranna 2008-06-11 10:28 am

    > pass 0 as the flags argument to RDI's constructor

    According to http://www.php.net/~helly/php/ext/spl/classRecursiveDirectoryIterator.html#be0e1176d512c66500e5c26f248c89c4
    you do not need to pass in 0, because __construct() of RDI already uses 0 as default value for flags.



About

My name is Evert, and I've been writing semi-regularly on this blog since 2006.

I'm currently available for contract work.

more info.

Subscribe

Dropbox

Dropbox is a simple cross-platform online backup and sync application. The first 2GB of space is free, and both you and me get an extra 250MB extra space if you sign up through this link.