Checking if a directory is empty when having over a million files inside I have the following function to confirm if a directory contains files:

/**
 * Check if the directory is empty
 * 
 * Function to ascertain if the specified directory contains files.
 * Comparing to two, because parent and current are present inside
 * the returned array. Only 3+ denotes files on the target dir.
 * 
 * @param str $dir              Directory to scan.
 * @param bol $count            Whether the return value should be the count result
 * 
 * @return bool|int Integer with count, TRUE or FALSE for check
 */
public function directory_with_contents($dir, $count = false) {

    try {
        if (!is_readable($dir)) return NULL;

        if ($count) {
            return count(scandir($dir));
        } else {
            return (count(scandir($dir)) == 2) ? false : true;
        }
    }
    catch(PDOException $e) {
        throw new userman_Exception("&lt;h1&gt;ups!&lt;/h1&gt;&lt;br/&gt;". $e-&gt;getMessage());
    }

}


The functions works well, but it is being used with directories that contain over one million files inside. The scandir() takes his time to return the results, and in turn this function with a large amount of files becomes slow.

Is any optimization that can be done as to have this function performing any faster when dealing with directories that have a large number of files?
Why is there a catch for a PDOException?  Also, why are you masking it with another exception?  That doesn't make much sense.  How is the final catch block supposed to know what it's actually catching?



Anyway, you need to use a lower-level method than scandir.  You could use a DirectoryIterator instance, but I would probably just go with opendir.

For example:

 function is_directory_empty($path)
 {
      $dir = opendir($path);
      while (($f = readdir($dir)) !== false) {
           if ($f !== '.' &amp;&amp; $f !== '..') {
                return true;
           }
      }
      return false;
  }


The important part here is that the loop bails upon finding the first file.  Additionally, . and .. will usually be the first two entries, so it should only have to run 3 times at maximum (though that is implementation specific, I believe, since the dots are not required to be first -- if the dots aren't first, it would run at most twice for an empty directory and once for a non-empty one).

It's worth noting that this function has terrible error handling.  In particular, there's no way to know if the directory is empty or the opendir call failed.  You could throw an exception:

if ($dir === false) {
     //I chose UnexpectedValueException because it's what DirectoryIterator throws
     throw new UnexpectedValueException("Unable to open directory: {$path}");
}


Another way would be to take a more procedural, C-esque approach:

define('DIR_EMPTY', 0);
define('DIR_NOT_EMPTY', 1);
define('DIR_ERROR_OPEN', 2);

function is_directory_empty($path)
{
    $dir = opendir($path);
    if ($dir === false) {
         return DIR_ERROR_OPEN;
    }
    while (($f = readdir($dir)) !== false) {
         if ($f !== '.' &amp;&amp; $f !== '..') {
              return DIR_EMPTY;
         }
    }
    return DIR_NOT_EMPTY;
}

$dir_empty = is_directory_empty("/some/path");
if ($dir_empty == DIR_EMPTY) {
    echo 'Empty!';
} else if ($dir_empty == DIR_NOT_EMPTY) {
    echo 'Not empty!';
} else {
    //(Should arguably be an else-if to check the last condition)
    echo 'Error opening path';
}




I would consider having your file-counting functionality, and your is-empty functionality be two separate functions.  There's a definite relation possible between them (is_empty(x) === !file_count(x)), but they're really different functionalities.

I'm not much a fan of a boolean flag changing the functionality of a function.  It's an anti-pattern in my opinion (and quite a few other people's opinion, though I'm too lazy to find links at the moment).

Instead, consider:

function count_directory_files($path)
{
    ...
}

function is_directory_empty($path)
{
    ...
}


The names clearly express the functionality.  There's no need for a magical flag.

directory_with_contents is a bit badly named to begin with, but if I had to guess what it does, I would guess that it returns true if a directory is empty, and false otherwise.  The counting-functionality is hidden.

(On the bad naming note: what does directory_with_contents mean?  Consider if you hadn't named it.  Could you look at that and know, with certainty, what it does?  I would imagine not.  In my opinion, functions that return booleans should typically be named as a binary predicate: is_&lt;object&gt;_&lt;property&gt;, can_&lt;object&gt;_&lt;property&gt;, etc.  [I'm actually a fan of camelCase, like, isDirectoryEmpty, but that's a superfluous opinion to this post :p.])