3

I'm building a file browser, and I need to know if a directory has children (but not how many or what type).

What's the most efficient way to find if a directory has children? glob()? scandir() it? Check its tax records?

Edit

It seems I was misunderstood, although I thought I was pretty clear. I'll try to restate my question.

What is the most efficient way to know if a directory is not empty? I'm basically looking for a boolean answer - NOT EMPTY or EMPTY.

I don't need to know:

  • how many files are in the directory
  • what the files are
  • when they were modified
  • etc.

I do need to know:

  • does the directory have any files in it at all

efficiently.

Ben
  • 54,723
  • 49
  • 178
  • 224
  • See my answer to this question "[finding files in a dir](http://stackoverflow.com/questions/5959545/finding-files-in-a-dir/5959577#5959577) ", it will help you read a directory – Ibu Jul 22 '11 at 05:30

5 Answers5

12

I think this is very efficient:

function dir_contains_children($dir) {
    $result = false;
    if($dh = opendir($dir)) {
        while(!$result && ($file = readdir($dh)) !== false) {
            $result = $file !== "." && $file !== "..";
        }

        closedir($dh);
    }

    return $result;
}

It stops the listing of the directories contents as soon as there is a file or directory found (not including the . and ..).

Ben
  • 54,723
  • 49
  • 178
  • 224
vstm
  • 12,407
  • 1
  • 51
  • 47
  • I know i posted an other answer, but i'd mark this as the best answer because, if you in theory had a dir with 1 million files, this function would only read a few lines while my function would load all files into an array, and then count the array. +1 from me. ;) – Kristoffer la Cour Jul 22 '11 at 07:18
  • Thanks anyway vstm and Kristoffer, but I prefer my own solution (below) until something better arrives. – Ben Jul 22 '11 at 07:23
2

You could use 'find' to list all empty directories in one step:

exec("find '$dir' -maxdepth 1 -empty -type d",$out,$ret);
print_r($out);

Its not "pure" php but its simple and fast.

towe75
  • 1,470
  • 10
  • 9
  • Hmmm, this is interesting, although it opens a shell :/ but I'll have a look, +1 for originality, thanks for bringing something new to the table. – Ben Jul 22 '11 at 07:24
  • It depends on your environment, whether its trusted or not... We're mostly deploying appliances with a fixed OS, so opening a shell is not a big issue here ;-) – towe75 Jul 22 '11 at 08:11
  • For windows: `$dir = escapeshellarg($dir); exec("tree $dir /a", $out, $ret);` then check the `$out` array - much faster than iterating. – Frank Forte Apr 05 '16 at 19:46
  • FYI, this answer is great for listing directories recursively, without the need to iterate through all of the files (it seems any PHP method that iterates is very slow if you have e.g. 5000+ files). Parsing the directory tree taken from the Windows command was not fun. – Frank Forte Apr 05 '16 at 19:51
2

This should do, easy, quick and effective.

<?php
function dir_is_empty($dir) {
  $dirItems = count(scandir($dir));
  if($dirItems > 2) return false;
  else return true;
}
?>
Kristoffer la Cour
  • 2,591
  • 3
  • 25
  • 36
2

Unfortunately, each solution so far has lacked the brevity and elegance necessary to shine above the rest.

So, I was forced to homebrew a solution myself, which I'll be implementing until something better pops up:

if(count(glob($dir."/*")) { 
  echo "NOT EMPTY"; 
}

Still not sure of the efficiency of this compared to other methods, which was the original question.

Ben
  • 54,723
  • 49
  • 178
  • 224
  • 1
    This is not nearly as efficient as vstm's answer. glob is going to bring the entire result set into memory. brevity != elegance. – Paolo Bergantino Mar 07 '14 at 17:00
  • You should change the accepted answer. I don't think this is the best solution. Efficiency is far more important here. – BadHorsie Apr 14 '15 at 11:49
1

I wanted to expand vstm's answer - Check only for child directories (and not files):

/**
* Check if directory contains child directories.
*/
function dir_contains_children_dirs($dir) {
  $result = false;
    if($dh = opendir($dir)) {
       while (!$result && ($file = readdir($dh))) {
         $result = $file !== "." && $file !== ".." && is_dir($dir.'/'.$file);
       }
       closedir($dh);
    }

  return $result;
}
amurrell
  • 2,383
  • 22
  • 26