C faster way to check if a directory exists
Asked Answered
P

5

24

I'm using opendir function to check if a directory exists. The problem is that I'm using it on a massive loop and it's inflating the ram used by my app.

What is the best (fastest) way to check if a directory exists in C? What is the best (fastest) way to create it if doesn't exists?

Preponderance answered 16/2, 2012 at 16:2 Comment(2)
Silly question, are you calling closedir() afterwards?Dessalines
And the faster way might be to do it asynchronously, but you should consider the capabilities of your media. If it is regular HDD then it might fail into seek-storm and this will work slow. But if you use RAID/SSD or even working in the cloud, this will work.Importunity
H
25

You could call mkdir(). If the directory does not exist then it will be created and 0 will be returned. If the directory exists then -1 will be returned and errno will be set to EEXIST.

Hamitic answered 16/2, 2012 at 16:4 Comment(6)
With the caveat that ENOENT may occur if something along the path doesn't exist as well.Dessalines
True. Should have mentioned that.Hamitic
Since you want to create the directory if it doesn't exist: yes. You save a stat() call.Hamitic
Note that you need to include <sys/stat.h> (for mkdir) and <errno.h> (to handle errno and EEXIST).Headsman
@Hamitic : If the directory exists in 99 % of cases, and if stat is faster than mkdir (which I don't have a clue about), your statement may not be true.Headsman
Note however that if you DON'T WANT to create the directory (but only check for existence, per first half of the question), then then mkdir costs you I/O (might be synchronized, costing an even greater hit in I/O performance for other actors on the system) and might fail for reasons unrelated to existence such as current account's permissions, mount options (R/O FS), or available filesystem space or quota.Audet
C
50

Consider using stat. S_ISDIR(s.st_mode) will tell you if it's a directory.

Sample:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

...
struct stat s;
int err = stat("/path/to/possible_dir", &s);
if(-1 == err) {
    if(ENOENT == errno) {
        /* does not exist */
    } else {
        perror("stat");
        exit(1);
    }
} else {
    if(S_ISDIR(s.st_mode)) {
        /* it's a dir */
    } else {
        /* exists but is no dir */
    }
}
...
Chazan answered 16/2, 2012 at 16:8 Comment(5)
how faster does it is comparing with opendir?Preponderance
That depends on the operating system and the number of entries there are in the parent directory. It will be faster in any way and that's what stat is made for.Chazan
Would lstat also be an option?Amenable
@Amenable , yes, I think lstat would possibly be the even better option because it does not follow symlinks. Depends on what is wanted though...Chazan
I am using this to test for "D:\path\subpath" and I've created the directory. It is telling me the dir does not exist. :/ (using Windows/MinGW)Gaona
H
25

You could call mkdir(). If the directory does not exist then it will be created and 0 will be returned. If the directory exists then -1 will be returned and errno will be set to EEXIST.

Hamitic answered 16/2, 2012 at 16:4 Comment(6)
With the caveat that ENOENT may occur if something along the path doesn't exist as well.Dessalines
True. Should have mentioned that.Hamitic
Since you want to create the directory if it doesn't exist: yes. You save a stat() call.Hamitic
Note that you need to include <sys/stat.h> (for mkdir) and <errno.h> (to handle errno and EEXIST).Headsman
@Hamitic : If the directory exists in 99 % of cases, and if stat is faster than mkdir (which I don't have a clue about), your statement may not be true.Headsman
Note however that if you DON'T WANT to create the directory (but only check for existence, per first half of the question), then then mkdir costs you I/O (might be synchronized, costing an even greater hit in I/O performance for other actors on the system) and might fail for reasons unrelated to existence such as current account's permissions, mount options (R/O FS), or available filesystem space or quota.Audet
R
20

I prefer using access()

if (0 != access("/path/to/possible_dir/", F_OK)) {
  if (ENOENT == errno) {
     // does not exist
  }
  if (ENOTDIR == errno) {
     // not a directory
  }
}

If you ensure a trailing / in the directory name, this works perfectly.

Resor answered 7/3, 2013 at 15:12 Comment(2)
Could you point me to where you found the bit about the trailing slash? The access() man page does not seem to say anything about it.Perea
This is the best reference I could find: pubs.opengroup.org/onlinepubs/009695399/basedefs/…Resor
C
3

I would use stat(), if available.

Conversational answered 16/2, 2012 at 16:6 Comment(0)
L
0

It sounds like you have a memory leak. Calling opendir should not inflate the RAM of your app as long as you remember to always call closedir after successfully opening a directory. Also, make sure you are freeing any buffers you allocated to compute the directory name.

Leto answered 16/2, 2012 at 16:9 Comment(1)
Yeap I'm closing it, I'll just use stat, thanks for your time!Preponderance

© 2022 - 2024 — McMap. All rights reserved.