Create a full path in C++(17)

January 19, 2017 · 2 minutes to read · C++, C++17, Linux

Sometimes, you must create a path in an application. The main function to use on Posix is mkdir, but it is limited to one directory.

When you want a full path like ./users/romain/tests/test1, but you do not know which parts exist, I have a function for this.

Snippet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <string>
#include <experimental/string_view>
#include <regex>
#include <list>

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

using namespace std;

int mkpath(const std::string& str)
{
    experimental::string_view sv(str);
    decltype(sv)::size_type pos = 0, next = 0;
    while (true)
    {
        if ((next = sv.find('/', pos)) == decltype(sv)::npos)
            next = sv.size();

        decltype(sv) sub = sv.substr(0, next);
        cout << "- " << sub.data() << endl;
        pos = next + 1;

        //if (::mkdir(string(sub).c_str(), 0755) == -1)
        if (::mkdir(sub.data(), 0755) == -1)
        {
            if (errno != EEXIST)
            {
                return -1;
            }
        }

        if (next == sv.size())
            break;
    }

    return 0;
}

int main()
{
    mkpath("./users/romain/tests/test1");

    return 0;
}

I use a new feature from C++17, called string_view.

This class as members pointing towards a string, but do not hold it. It is lighter than a full copy!

If you do not have C++17, you can easily replace a string_view by a simple string. All method calls stay the same.

Improvement

In C++17, there is also an override for mkdir called create_directory in the namespace std::filesystem.

I will write a most complete post on this new header.

References