How can I create directory tree in C++/Linux? How can I create directory tree in C++/Linux? linux linux

How can I create directory tree in C++/Linux?


Easy with Boost.Filesystem: create_directories

#include <boost/filesystem.hpp>//...boost::filesystem::create_directories("/tmp/a/b/c");

Returns: true if a new directory was created, otherwise false.


With C++17 or later, there's the standard header <filesystem> withfunctionstd::filesystem::create_directorieswhich should be used in modern C++ programs.The C++ standard functions do not have the POSIX-specific explicitpermissions (mode) argument, though.

However, here's a C function that can be compiled with C++ compilers.

/*@(#)File:           mkpath.c@(#)Purpose:        Create all directories in path@(#)Author:         J Leffler@(#)Copyright:      (C) JLSS 1990-2020@(#)Derivation:     mkpath.c 1.16 2020/06/19 15:08:10*//*TABSTOP=4*/#include "posixver.h"#include "mkpath.h"#include "emalloc.h"#include <errno.h>#include <string.h>/* "sysstat.h" == <sys/stat.h> with fixup for (old) Windows - inc mode_t */#include "sysstat.h"typedef struct stat Stat;static int do_mkdir(const char *path, mode_t mode){    Stat            st;    int             status = 0;    if (stat(path, &st) != 0)    {        /* Directory does not exist. EEXIST for race condition */        if (mkdir(path, mode) != 0 && errno != EEXIST)            status = -1;    }    else if (!S_ISDIR(st.st_mode))    {        errno = ENOTDIR;        status = -1;    }    return(status);}/**** mkpath - ensure all directories in path exist** Algorithm takes the pessimistic view and works top-down to ensure** each directory in path exists, rather than optimistically creating** the last element and working backwards.*/int mkpath(const char *path, mode_t mode){    char           *pp;    char           *sp;    int             status;    char           *copypath = STRDUP(path);    status = 0;    pp = copypath;    while (status == 0 && (sp = strchr(pp, '/')) != 0)    {        if (sp != pp)        {            /* Neither root nor double slash in path */            *sp = '\0';            status = do_mkdir(copypath, mode);            *sp = '/';        }        pp = sp + 1;    }    if (status == 0)        status = do_mkdir(path, mode);    FREE(copypath);    return (status);}#ifdef TEST#include <stdio.h>#include <unistd.h>/*** Stress test with parallel running of mkpath() function.** Before the EEXIST test, code would fail.** With the EEXIST test, code does not fail.**** Test shell script** PREFIX=mkpath.$$** NAME=./$PREFIX/sa/32/ad/13/23/13/12/13/sd/ds/ww/qq/ss/dd/zz/xx/dd/rr/ff/ff/ss/ss/ss/ss/ss/ss/ss/ss** : ${MKPATH:=mkpath}** ./$MKPATH $NAME &** [...repeat a dozen times or so...]** ./$MKPATH $NAME &** wait** rm -fr ./$PREFIX/*/int main(int argc, char **argv){    int             i;    for (i = 1; i < argc; i++)    {        for (int j = 0; j < 20; j++)        {            if (fork() == 0)            {                int rc = mkpath(argv[i], 0777);                if (rc != 0)                    fprintf(stderr, "%d: failed to create (%d: %s): %s\n",                            (int)getpid(), errno, strerror(errno), argv[i]);                exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);            }        }        int status;        int fail = 0;        while (wait(&status) != -1)        {            if (WEXITSTATUS(status) != 0)                fail = 1;        }        if (fail == 0)            printf("created: %s\n", argv[i]);    }    return(0);}#endif /* TEST */

The macros STRDUP() and FREE() are error-checking versions ofstrdup() and free(), declared in emalloc.h (and implemented inemalloc.c and estrdup.c).The "sysstat.h" header deals with broken versions of <sys/stat.h>and can be replaced by <sys/stat.h> on modern Unix systems (but therewere many issues back in 1990).And "mkpath.h" declares mkpath().

The change between v1.12 (original version of the answer) and v1.13(amended version of the answer) was the test for EEXIST indo_mkdir().This was pointed out as necessary bySwitch — thankyou, Switch.The test code has been upgraded and reproduced the problem on a MacBookPro (2.3GHz Intel Core i7, running Mac OS X 10.7.4), and suggests thatthe problem is fixed in the revision (but testing can only show thepresence of bugs, never their absence).The code shown is now v1.16; there have been cosmetic or administrativechanges made since v1.13 (such as use mkpath.h instead of jlss.h andinclude <unistd.h> unconditionally in the test code only).It's reasonable to argue that "sysstat.h" should be replaced by<sys/stat.h> unless you have an unusually recalcitrant system.

(You are hereby given permission to use this code for any purpose with attribution.)

This code is available in my SOQ(Stack Overflow Questions) repository on GitHub as files mkpath.c andmkpath.h (etc.) in thesrc/so-0067-5039sub-directory.


system("mkdir -p /tmp/a/b/c")

is the shortest way I can think of (in terms of the length of code, not necessarily execution time).

It's not cross-platform but will work under Linux.