Create Multiple Level Subdirectories

While recently working on a project, I needed to create a series of subdirectories from a user supplied string. These could be two, three, four or more deep. Of course the MSVC Help files lived up to their normal level of support. After beating my head aginst the wall I finally realized I could only create a single subdirectory at one time. In other words if none of the sub-directories previously existed then the code CreateDirectory("C:\Data\Test\Monday\Backup\Archive") would continually fail.

I finally realized that the function CreateDirectory is only a wrapper for _mkdir which will only create a single sub-directory so I would need to recursively call CreateDirectory() several times. Since there is really no way around this I created a small subroutine WriteDir() which takes care of all of the work for me.

What are the steps required

  • Set up a CStringArray to hold the Directories in order on creation.
  • Parse the passed CString Object into the CString variable tem one character at a time.
  • When we get to a \ pass it up and add "tem" to the CStringArray.
  • We need to add the \ at the end of the tem variable in order to continue to separate the directories.
  • Continue to do this until the entire string is parsed.

    **Note** Notice we have to add the final value of tem to the CString Array since there is NO \ at the end of the Directory String

    Now we can start creating the directories
  • Skip the first entry since it is the Drive letter
  • Cycle through the CStringArray testing to see if the directory already exists. If it does then go to the next item.
  • If the directory does not exist then use CreateDirectory().
  • When we reach the end of the CStringArray, check to see if the full directory actually was created. If it was then return TRUE, otherwise return FALSE;
  • Don't forget to clear the array (Good Housekeeping)

    From the Example: Original CString = C:\Data\Test\Monday\Backup\Archive
    CStringArray members
    	[0] = C:
    	[1] = C:\Data
    	[2] = C:\Data\Test
    	[3] = C:\Data\Test\Monday
    	[4] = C:\Data\Test\Monday\Backup
    	[5] = C:\Data\Test\Monday\Backup\Archive
    Remeber we skipped the first entry.  
    Then we cycled through and created each string independently.

    How do we put this to use

    Add the files WriteDir.h and WriteDir.cpp to your project. Add #include "WriteDir.h" in the cpp file where you are going to call the function. Set up a test variable: BOOL test; CString someString; Set someString to a Directory path you need to create (Do not add a \ at the end of the string) test = WriteDir(someString);

    if test == TRUE   SUCCESS
    if test == FALSE  FAILURE

    The Source Code

    #include "stdafx.h"
    #include "WriteDir.h"

    Setup Internal Variables

    BOOL WriteDirectory(CString dd)
    	HANDLE		fFile;		// File Handle
    	WIN32_FIND_DATA	fileinfo;	// File Information Structure
    	CStringArray	m_arr;		// CString Array to hold Directory Structures
    	BOOL tt;			// BOOL used to test if Create Directory was successful
    	int x1 = 0;			// Counter
    	CString tem = "";		// Temporary CString Object
     Before we go to a lot of work. Check to see if the Directory exists
    	fFile = FindFirstFile(dd,&fileinfo);
    	// if the file exists and it is a directory
    	if(fileinfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
    		//  Directory Exists close file and return
    		return TRUE;
    	m_arr.RemoveAll();				// Not really necessary - Just habit
    Separate the String into its compounded components
    	for(x1 = 0; x1 < dd.GetLength(); x1++ )		// Parse the supplied CString Directory String
    		if(dd.GetAt(x1) != '\\')		// if the Charachter is not a \ 
    			tem += dd.GetAt(x1);		// add the character to the Temp String
    			m_arr.Add(tem);			// if the Character is a \ 
    								Add the Temp String to the CString Array
    			tem += "\\";			// Now add the \ to the temp string
    		if(x1 == dd.GetLength()-1)		// If we reached the end of the String
    								add the remaining string
    	// Close the file
    Create each level of the Directory Structure
    	// Now lets cycle through the String Array and create each directory in turn
    	for(x1 = 1; x1 < m_arr.GetSize(); x1++)
    		tem = m_arr.GetAt(x1);
    		tt = CreateDirectory(tem,NULL);
    		// If the Directory exists it will return a false
    		// If we were successful we set the attributes to normal
    	//  Now lets see if the directory was successfully created
    	fFile = FindFirstFile(dd,&fileinfo);
    Check to see if the Directory was created and it actually is a Directory
    	if(fileinfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
    		//  Directory Exists close file and return
    		return TRUE;
    		// For Some reason the Function Failed  Return FALSE
    		return FALSE;

    Download source - 2 KB

  • Comments

    • WriteDirectory() fails sporadically, fix found.

      Posted by Chr on 08/14/2012 08:10am

      WriteDirectory() sporadically failed. My computer is running windows 7/32. I could fix the problem by checking the result of FindFirstFile(). This does not make sense, because FindClose() should also work with invalid handles, however this fix works: fFile = FindFirstFile(cs_directory_to_create,&fileinfo); if (INVALID_HANDLE_VALUE != fFile) { ...

    • Bug Fix

      Posted by rossini on 07/06/2004 03:02pm

      You should change the line
      if(fileinfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
       to if ((fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
      The problem is that if the directory has more than just the
      directory attribute set the check will fail.  I found this
      out by turning off the "Allow Indexing Service to index
      this disk for fast file searching" under properties for the
      drive in Windows XP.  This added the attribute 
      thus causing the checks for the directory to fail.

    • Create folder by current date

      Posted by Legacy on 01/22/2004 12:00am

      Originally posted by: san dinfer

      can any one help me how to create a folder

    • please help me in creating folders

      Posted by Legacy on 01/19/2004 12:00am

      Originally posted by: afsheen nasir

      I want to create folder with vc++ code anybody can help me???

      • A Lame Attempt !..

        Posted by prasadptc on 10/13/2004 08:54am

        int main()
        char pStrName[64];
        char pStrDirectory[100];
        cout<<"Enter The Name Of Folder To Be Create on C Drive:"<

    • SHCreateDirectory API

      Posted by Legacy on 12/17/2003 12:00am

      Originally posted by: Josh Hogle

      If your code is for Windows 2000 or later, check out the SHCreateDirectory API call.

    • Permissions under "Inetpub/wwwroot/" NEED HELP

      Posted by Legacy on 08/16/2002 12:00am

      Originally posted by: BOBA KOPOBbEB

      2000 ONLY.
      Looks fine at first glance, but acctually failed somewhere on the road. Take a look at Ownership/Auditing


      // security inits
      memset ( ( VOID *) &sa, 0, sizeof ( SECURITY_ATTRIBUTES) );

      // alloc & init SD
      if ( ! ( pSD = ( PSECURITY_DESCRIPTOR)

      if ( ! InitializeSecurityDescriptor ( pSD,

      // specify inheritanse
      UINT res = SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
      printf("- ret = %d\n", res);

      // set NULL DACL on the SD
      if ( ! SetSecurityDescriptorDacl ( pSD, TRUE, ( PACL) NULL, FALSE) )

      // now set up the security attributes
      sa.nLength = sizeof ( SECURITY_ATTRIBUTES);
      sa.bInheritHandle = TRUE;
      sa.lpSecurityDescriptor = pSD;

      BOOL ret = CreateDirectory((LPCTSTR)path, &sa);

    • Simple version without any classes, recursion and uneccessary memory allocations

      Posted by Legacy on 07/10/2002 12:00am

      Originally posted by: Eugen

      BOOL CreateDirectoryTree(LPCTSTR pszDirectory)
      char szDir[MAX_PATH];
      char *p, *pNext;

      strcpy (szDir, pszDirectory);
      pNext = strchr(szDir, '\\');
      if (pNext)
      while ((p=strchr(pNext, '\\')) != 0)
      *p = 0;
      if (GetFileAttributes (szDir) == -1)
      if (CreateDirectory(szDir, 0) == FALSE)
      return FALSE;
      *p = '\\';
      pNext = p+1;
      if (GetFileAttributes (szDir) == -1)
      if (CreateDirectory(szDir, 0) == FALSE)
      return FALSE;
      return TRUE;

      • Potential buffer overflow!

        Posted by inbugable on 09/28/2004 06:59am

        strcpy (szDir, pszDirectory); is bad
        char szDir[MAX_PATH+1]; 
        strncpy (szDir, pszDirectory,MAX_PATH);
        szDir[MAX_PATH] = 0;

    • Try SHPathPrepareForWrite()

      Posted by Legacy on 06/12/2002 12:00am

      Originally posted by: Patrick Walsh

      You will get a kick out of this one.
      It will even prompt the user to format the drive if not formated, mount the network drive etc...

    • Problems using recursive logic

      Posted by Legacy on 11/15/2001 12:00am

      Originally posted by: Ashes

      Although recursive logic might be simpler to code, recursive functions use up a lot more stack space. So, the non-recursive original code might be more useful, especially if I am creating very deeply nested paths (4K or greater).

      However, I agree using the ImageHlp API is probably the best.

    • WOW !!

      Posted by Legacy on 06/08/2001 12:00am

      Originally posted by: Vikas

      See 'MakeSureDirectoryPathExists()'

      This's really cool !!
      Excellent method to create multiple level of SubDirectories !!

    • Loading, Please Wait ...

    Leave a Comment
    • Your email address will not be published. All fields are required.

    Top White Papers and Webcasts

    • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

    • Enterprises are increasingly looking to platform as a service (PaaS) to lower their costs and speed their time to market for new applications. Developing, deploying, and managing applications in the cloud eliminates the time and expense of managing a physical infrastructure to support them. PaaS offerings must deliver additional long-term benefits, such as a lower total cost of ownership (TCO), rapid scalability, and ease of integration, all while providing robust security and availability. This report …

    Most Popular Programming Stories

    More for Developers

    RSS Feeds

    Thanks for your registration, follow us on our social networks to keep up-to-date