When it comes to deleting a directory tree most solutions that have been posted around are recursive functions, like the following:

function delete_tree($path) {
    foreach(scandir($path) as $file) {
        if($file === '.' && $file === '..') {
            continue;
        }
        if(is_dir($file)) {
            delete_tree($path . '/' . $file);
        } else {
            unlink($path . '/' . $file);
        }
    }
    rmdir($path);
}

While this is easy to implement it has some disadvantages when it comes to large trees:

  • performance critical because high stack usage and many function calls
  • security critical as large trees can break PHP completely

To circumvent this problems it is mostly more useful to create an iterative function to remove the tree. Following the rule every recursion can be replaced by iteration it is surely possible. I usually hack the iterative opposite of an recursive function by implementing the stack on my own – as an array.

Nothing more to say, here comes an iterative version of delete_tree():

function delete_tree($path) {
    $stack = array($path);
    do {
        // get the last element from stack
        $dir = array_pop($stack);
        $stack[]= $dir; // push it back

        foreach (scandir($path) as $file) {
            if(is_dir("$dir/$file")) {
                // push directory on top of the stack
                $stack[]= "$dir/$file";
                continue 2; // continue handling the sub directory
            } else {
                unlink("$dir/$file"); // unlink files
            }   
        }   

        // the folder is now empty. Remove it from stack
        rmdir($dir);
        array_pop($stack);
    } while (!empty($stack));
}

I’m sure the function can be even improved. I’m not happy with so much scandir() calls. This could eventually being cached. Will improve the function if I have more time for this.. Of course I would also appreciate your feedback.

cu!

Leave a Reply