Check if a directory is empty using C on Linux

Viewed 21948

Is this the right way of checking whether a directory is empty or not in C? Is there a more efficient way to check for an empty directory, especially if it has 1000s of files if not empty?

int isDirectoryEmpty(char *dirname) {
  int n = 0;
  struct dirent *d;
  DIR *dir = opendir(dirname);
  if (dir == NULL) //Not a directory or doesn't exist
    return 1;
  while ((d = readdir(dir)) != NULL) {
    if(++n > 2)
      break;
  }
  closedir(dir);
  if (n <= 2) //Directory Empty
    return 1;
  else
    return 0;
}

If its an empty directory, readdir will stop after the entries '.' and '..' and hence empty if n<=2.

If its empty or doesn't exist, it should return 1, else return 0

Update:

@c$ time ./isDirEmpty /fs/dir_with_1_file; time ./isDirEmpty /fs/dir_with_lots_of_files
0

real    0m0.007s
user    0m0.000s
sys 0m0.004s

0

real    0m0.016s
user    0m0.000s
sys 0m0.008s

Why does it take longer to check for a directory with lots of files as compared to one with just one file?

3 Answers

There could be a tricky strategy referred to a command-line rmdir which couldn't remove a non-empty directory, and this feature could be used to detect if a directory is empty. To do this, try to remove a directory by calling system("rmdir your_directory"). If the directory isn't empty, the function fails and returns a non-zero value, and probably prompts you rmdir: failed to remove 'your_directory': Directory not empty. The prompt could be muted by redirecting stderr into /dev/null, and doing the mute could increase its performance. Otherwise, the directory will be removed, then you could restore it by creating it again.

This strategy would be helpful if there are any hidden files in the directory, it's still able to detect their existence. And rmdir returns immediately regardless of how many files are in a non-empty directory in my case.

But pay attention to the command aliases, especially in the *nix shell environment, if there are any aliases of rmdir command which added some arguments that causes rmdir to do recursive file deletion, the trick will fail and causes all of the directories to be actually removed. This could be solved by calling system("\rmdir your_directory") which removes the alias.

Related