Search code examples
creaddir

readdir looping more times than number of files present in the directory


My goal is to count the number of files in a directory. After searching around, I found a piece of code which iterates over each file in a directory. But the issue is that it's looping extra times, 2 times extra to be more precise.

So for

int main(void)
{   
  DIR           *d;
  struct dirent *dir;  
  char *ary[10000];
  char fullpath[256];  
  d = opendir("D:\\frames\\");
  if (d)
  {    
   int count = 1;
    while ((dir = readdir(d)) != NULL)
    {  
       snprintf(fullpath, sizeof(fullpath), "%s%d%s", "D:\\frames\\", count, ".jpg");
       int fs = fsize(fullpath);
       printf("%s\t%d\n", fullpath, fs); // using this line just for output purposes
      count++;      
    }      
    closedir(d);
  }
  getchar();
  return(0);
}

My folder contains 500 files, but the output is shown till 502enter image description here

UPDATE

I modified the code to read as

struct stat buf;
if ( S_ISREG(buf.st_mode) ) // <-- I'm assuming this says "if it is a file"
{
  snprintf(fullpath, sizeof(fullpath), "%s%d%s", "D:\\frames\\", count, ".jpg");
  int fs = fsize(fullpath);
  printf("%s\t%d\n", fullpath, fs);
}

But I'm getting storage size of "buf" isn't known. I also tried doing struct stat buf[100], but that didn't help either.


Solution

  • As pointed out in comments, you're also getting the two directories named . and .., which skews your count.

    In Linux, you can use the d_type field of the struct dirent to filter them out, but the documentation says:

    The only fields in the dirent structure that are mandated by POSIX.1 are: d_name[], of unspecified size, with at most NAME_MAX characters preceding the terminating null byte; and (as an XSI extension) d_ino. The other fields are unstandardized, and not present on all systems; see NOTES below for some further details.

    So, assuming you're on Windows you probably don't have d_type. Then you can use some other call instead, for instance stat(). You can of course filter out based on name too, but if you want to skip directories anyway that is a more robust and general solution.