I\'m trying to create a function that takes the name of a directory (C:\\foo\\bar
, or ..\\foo\\bar\\..\\baz
, or \\\\someserver\\foo\\bar
Here is my example of code (copied from How can I create directory tree in C++/Linux?). Maybe it's not conform all requirements from first post, but pretty well and it works for both Windows and Linux:
#include <iostream>
#include <string>
#include <sys/stat.h> // stat
#include <errno.h> // errno, ENOENT, EEXIST
#if defined(_WIN32)
#include <direct.h> // _mkdir
#endif
bool isDirExist(const std::string& path)
{
#if defined(_WIN32)
struct _stat info;
if (_stat(path.c_str(), &info) != 0)
{
return false;
}
return (info.st_mode & _S_IFDIR) != 0;
#else
struct stat info;
if (stat(path.c_str(), &info) != 0)
{
return false;
}
return (info.st_mode & S_IFDIR) != 0;
#endif
}
bool makePath(const std::string& path)
{
#if defined(_WIN32)
int ret = _mkdir(path.c_str());
#else
mode_t mode = 0755;
int ret = mkdir(path.c_str(), mode);
#endif
if (ret == 0)
return true;
switch (errno)
{
case ENOENT:
// parent didn't exist, try to create it
{
int pos = path.find_last_of('/');
if (pos == std::string::npos)
#if defined(_WIN32)
pos = path.find_last_of('\\');
if (pos == std::string::npos)
#endif
return false;
if (!makePath( path.substr(0, pos) ))
return false;
}
// now, try to create again
#if defined(_WIN32)
return 0 == _mkdir(path.c_str());
#else
return 0 == mkdir(path.c_str(), mode);
#endif
case EEXIST:
// done!
return isDirExist(path);
default:
return false;
}
}
int main(int argc, char* ARGV[])
{
for (int i=1; i<argc; i++)
{
std::cout << "creating " << ARGV[i] << " ... " << (makePath(ARGV[i]) ? "OK" : "failed") << std::endl;
}
return 0;
}
Usage:
d:\Work\c++\make_path> makePath 1/2 folderA/folderB/folderC
creating 1/2 ... OK
creating folderA/folderB/folderC ... OK
If you don't need to support Windows versions prior to Windows 2000, you can use the SHCreateDirectoryEx function for this. Consider this:
int createDirectoryRecursively( LPCTSTR path )
{
return SHCreateDirectoryEx( NULL, path, NULL );
}
// ...
if ( createDirectoryRecursively( T("C:\\Foo\\Bar\\Baz") ) == ERROR_SUCCESS ) {
// Bingo!
}
In case using such shell32.dll API ever becomes an issue, you can always reimplement the createDirectoryRecursively function above with something else (possibly a hand-wired loop).
From http://www.cplusplus.com/reference/string/string/find_last_of/:
// string::find_last_of
#include <iostream>
#include <string>
using namespace std;
void SplitFilename (const string& str)
{
size_t found;
cout << "Splitting: " << str << endl;
found=str.find_last_of("/\\");
cout << " folder: " << str.substr(0,found) << endl;
cout << " file: " << str.substr(found+1) << endl;
}
int main ()
{
string str1 ("/usr/bin/man");
string str2 ("c:\\windows\\winhelp.exe");
SplitFilename (str1);
SplitFilename (str2);
return 0;
That should give you an idea on how to deal with the path string. Then after that, all you need to do is loop through the paths starting from the drive down to the deepest folder. Check if the folder exists, and if it doesn't, create it.
With C++17, this can be done quite easily using std::filesystem::create_directories().
Example:
#include <filesystem>
...
const char* path = "C:\\foo\\bar";
std::filesystem::create_directories(path);
I'm modifying an old Windows CE app, and this is what I'm planning to use. Should work in Windows CE, too. This is actually recursive, too:
static void createPath(const CString& p)
{
// only create directories that don't exist
if (::GetFileAttributes(p) == INVALID_FILE_ATTRIBUTES)
{
// check if our parent needs to be created, too...
int i = p.ReverseFind('\\');
if (i > 0)
{
// ...yes, create the parent (recursively)
createPath(p.Left(i));
}
// finally, actually create the directory in p
::CreateDirectory(p, NULL);
}
}
UnicodeString path = "C:\\Test\\Test\\Test\\";
TStringList *list = new TStringList();
try
{
list->Delimiter = '\\';
list->StrictDelimiter = true;
list->DelimitedText = path;
path = list->Strings[0]; \\drive letter
for(int i = 1; i < list->Count - 1; i++)
{
try
{
path += "\\" + list->Strings[i];
CreateDirectory(path.w_str(), NULL);
}
catch(...) { }
}
}
catch(...) { }
delete list;