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:

  $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'));

  foreach($files as $file) {

    // Do your stuff here, $file is an SplFileInfo object



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.

  $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'),RecursiveIteratorIterator::SELF_FIRST);