How do I recursively create a folder in Win32?
Solution 1:
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).
Solution 2:
Here's a version that works with no external libraries, so Win32-only, and that function in all versions of Windows (including Windows CE, where I needed it):
wchar_t *path = GetYourPathFromWherever();
wchar_t folder[MAX_PATH];
wchar_t *end;
ZeroMemory(folder, MAX_PATH * sizeof(wchar_t));
end = wcschr(path, L'\\');
while(end != NULL)
{
wcsncpy(folder, path, end - path + 1);
if(!CreateDirectory(folder, NULL))
{
DWORD err = GetLastError();
if(err != ERROR_ALREADY_EXISTS)
{
// do whatever handling you'd like
}
}
end = wcschr(++end, L'\\');
}
Solution 3:
Here is a function I wrote which iteratively creates a folder tree. Here is the main function:
#include <io.h>
#include <string>
#include <direct.h>
#include <list>
// Returns false on success, true on error
bool createFolder(std::string folderName) {
list<std::string> folderLevels;
char* c_str = (char*)folderName.c_str();
// Point to end of the string
char* strPtr = &c_str[strlen(c_str) - 1];
// Create a list of the folders which do not currently exist
do {
if (folderExists(c_str)) {
break;
}
// Break off the last folder name, store in folderLevels list
do {
strPtr--;
} while ((*strPtr != '\\') && (*strPtr != '/') && (strPtr >= c_str));
folderLevels.push_front(string(strPtr + 1));
strPtr[1] = 0;
} while (strPtr >= c_str);
if (_chdir(c_str)) {
return true;
}
// Create the folders iteratively
for (list<std::string>::iterator it = folderLevels.begin(); it != folderLevels.end(); it++) {
if (CreateDirectory(it->c_str(), NULL) == 0) {
return true;
}
_chdir(it->c_str());
}
return false;
}
The folderExists
routine is as follows:
// Return true if the folder exists, false otherwise
bool folderExists(const char* folderName) {
if (_access(folderName, 0) == -1) {
//File not found
return false;
}
DWORD attr = GetFileAttributes((LPCSTR)folderName);
if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
// File is not a directory
return false;
}
return true;
}
An example call I tested the above functions with is as follows (and it works):
createFolder("C:\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\l\\m\\n\\o\\p\\q\\r\\s\\t\\u\\v\\w\\x\\y\\z");
This function hasn't gone through very thorough testing, and I'm not sure it yet works with other operating systems (but probably is compatible with a few modifications). I am currently using Visual Studio 2010
with Windows 7.
Solution 4:
SHCreateDirectory function can do this. But the document states that it can get deprecated in later version of Windows.
From MSDN
Note This function is available through Windows XP Service Pack 2 (SP2) and Microsoft Windows Server 2003. It might be altered or unavailable in subsequent versions of Windows.
Solution 5:
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);