Skip to content

Instantly share code, notes, and snippets.

@danzek
Created April 13, 2017 21:34
Show Gist options
  • Save danzek/d7192d250c951804dec05125f5223a30 to your computer and use it in GitHub Desktop.
Save danzek/d7192d250c951804dec05125f5223a30 to your computer and use it in GitHub Desktop.
Create Directory Recursively with Windows API
/* From http://blog.nuclex-games.com/2012/06/how-to-create-directories-recursively-with-win32/
* Retrieved April 12, 2017
* Posted by user Cygon (http://blog.nuclex-games.com/author/cygon/)
*
* This code is free for the taking and you can use it however you want.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* As I just found out, the CreateDirectory function on Win32 can only create one directory at a time.
* If one, for example, specifies C:\Users\All Users\FirstNew\SecondNew as the directory to create, and
* both FirstNew and SecondNew do not exist, then CreateDirectory() fails.... Here's a workaround:
*/
/// <summary>Creates all directories down to the specified path</summary>
/// <param name="directory">Directory that will be created recursively</param>
/// <remarks>
/// The provided directory must not be terminated with a path separator.
/// </remarks>
void createDirectoryRecursively(const std::wstring &directory) {
static const std::wstring separators(L"\\/");
// If the specified directory name doesn't exist, do our thing
DWORD fileAttributes = ::GetFileAttributesW(directory.c_str());
if(fileAttributes == INVALID_FILE_ATTRIBUTES) {
// Recursively do it all again for the parent directory, if any
std::size_t slashIndex = directory.find_last_of(separators);
if(slashIndex != std::wstring::npos) {
createDirectoryRecursively(directory.substr(0, slashIndex));
}
// Create the last directory on the path (the recursive calls will have taken
// care of the parent directories by now)
BOOL result = ::CreateDirectoryW(directory.c_str(), nullptr);
if(result == FALSE) {
throw std::runtime_error("Could not create directory");
}
} else { // Specified directory name already exists as a file or directory
bool isDirectoryOrJunction =
((fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) ||
((fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
if(!isDirectoryOrJunction) {
throw std::runtime_error(
"Could not create directory because a file with the same name exists"
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment