Using RecursiveDirectoryIterator to delete empty directories

I have an upload form that creates a unique upload directory before the file is uploaded, meaning that when there is a form error or the user leaves the page, the empty directory remains on the server.

I am looking at using the RecursiveDirectoryIterator to delete directories that do not have contents, but am having some trouble with the simple manipulation. I have the following snippet:


$iterator = new RecursiveDirectoryIterator(realpath($this->getConfig()->fileDestination));
			foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) {
				if($file->isDir()){
		          	rmdir($file->getPathname());
		       	}else{
		          unlink($file->getPathname());
				}
			}

…but i’m looking for a simple function that i cannot find in the api anywhere, something like $file->isEmpty() (which would return false if the current directory contains no files or sub directories).

I feel like i’m missing something really obvious, so please give me a d’oh moment.

Hi skinny monkey,

There is no built-in method like an isEmpty() one but there isn’t too much work involved in finding out how many (if any) items are present within a directory such as you need.

Taking your existing code and adapting it to check (and remove) only for empty directories, your code might look like:


<?php

$iterator = new RecursiveDirectoryIterator(realpath($this->getConfig()->fileDestination));

// Skip "dot" files
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);

// Get directories only
$directories = new ParentIterator($iterator);

// Loop over directories and remove empty ones
foreach (new RecursiveIteratorIterator($directories, RecursiveIteratorIterator::SELF_FIRST) as $dir) {
        // Count the number of "children" from the main directory iterator
        if (iterator_count($iterator->getChildren()) === 0) {
                rmdir($dir->getPathname();
        }
}


You’ll notice a few changes. First is that instead of checking for directories using isDir() within the foreach loop, a ParentIterator is used instead; the idea being that only directories can potentially contain “children” items (other directories and files).

The next change is that we tell the directory iterator to skip “dot” files (. and …) which is important because otherwise they’ll be included in counting the contents of a folder. That counting is the important part, to get the number of items within a folder, the code uses the iterator_count() function on the children of the current folder being examined. If there are no children (no files or folders) then it is OK to remove the folder.

Oh and the code above uses SELF_FIRST rather than CHILD_FIRST purely because there will be no children to come first. :slight_smile: