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?

Frederico Schardong
  • 1,946
  • 6
  • 38
  • 62
  • 8
    Silly question, are you calling `closedir()` afterwards? – user7116 Feb 16 '12 at 16:04
  • 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. – LiMar Feb 16 '12 at 16:09

5 Answers5

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 */
    }
}
...
Johannes Weiss
  • 52,533
  • 16
  • 102
  • 136
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.

Kevin Brydon
  • 12,524
  • 8
  • 46
  • 76
ckruse
  • 9,642
  • 1
  • 25
  • 25
  • 2
    With the caveat that `ENOENT` may occur if something along the path doesn't exist as well. – user7116 Feb 16 '12 at 16:07
  • True. Should have mentioned that. – ckruse Feb 16 '12 at 16:08
  • Since you want to create the directory if it doesn't exist: yes. You save a ``stat()`` call. – ckruse Feb 16 '12 at 20:53
  • 1
    Note that you need to include (for `mkdir`) and (to handle `errno` and `EEXIST`). – Skippy le Grand Gourou Jul 21 '13 at 18:09
  • @ckruse : 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. – Skippy le Grand Gourou Jul 21 '13 at 18:18
  • 1
    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. – Jim Klimov Jul 21 '20 at 09:15
21

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.

To1ne
  • 1,108
  • 2
  • 12
  • 22
  • 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. – domsson Nov 23 '18 at 08:21
  • This is the best reference I could find: https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11 – To1ne Nov 26 '18 at 09:16
3

I would use stat(), if available.

unwind
  • 391,730
  • 64
  • 469
  • 606
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.

David Grayson
  • 84,103
  • 24
  • 152
  • 189