Recursive CreateDirectory

I found many examples of CreateDirectory recursively, but not the one I was looking for.

here is the specification

This input

  • \\ server \ folder \ aa \ bb \ ss
  • C: \ aa \ bb \ ss

USING the helper API

 CreateDirectory (char * path)
 returns true, if successful
 else
 FALSE

      

Condition: There must be no parsing to distinguish whether the path is local or shared.

Write a procedure in C or C ++

+2


source to share


8 answers


It seems to me it's pretty simple ... here is the version that works on every version of Windows:

unsigned int pos = 0;
do
{
    pos = path.find_first_of("\\/", pos + 1);
    CreateDirectory(path.substr(0, pos).c_str(), NULL);
} while (pos != std::string::npos);

      

Unicode:



pos = path.find_first_of(L"\\/", pos + 1);

      

Hello,

+5


source


This may be exactly what you want. It does not attempt to parse to distinguish whether the path is local or shared.

bool TryCreateDirectory(char *path){
    char *p;
    bool b;

    if(
        !(b=CreateDirectory(path))
        &&
        !(b=NULL==(p=strrchr(path, '\\')))
        ){
        size_t i;

        (p=strncpy((char *)malloc(1+i), path, i=p-path))[i]='\0';
        b=TryCreateDirectory(p);
        free(p);
        b=b?CreateDirectory(path):false;
    }

    return b;
}

      



The algorithm is pretty simple, just recursively pass the higher level directory string until creating the current directory level fails until success or higher level is achieved. When the inner call returns with success, create the current one. This method does not parse to determine the local or server system itself, according to CreateDirectory. In WINAPI, CreateDirectory will never allow you to create a "c:" or "\", when the path reaches that level, the method soon ends up calling it with path = "" and that won't work either. This is the reason why Microsoft defines a file naming rule like this for DOS path rule compatibility and to simplify coding efforts.

+2


source


Completely hack and unsafe and nothing you really would like to do in production code, but ...

Warning: here is the code that was entered in the browser:

int createDirectory(const char * path) {
  char * buffer = malloc((strlen(path) + 10) * sizeof(char));
  sprintf(buffer, "mkdir -p %s", path);
  int result = system(buffer);
  free(buffer);
  return result;
}

      

+1


source


How about using MakeSureDirectoryPathExists ()?

+1


source


Go through each level of the directory in the path, starting at the root, trying to create the next level.

If any of the calls to CreateDirectory fail, you can exit early, you will succeed if you get to the end of the path without crashing.

This assumes that calling CreateDirectory on a pre-existing path has no ill effects.

0


source


The requirement not to parse the pathname for server names is interesting as it appears to be required to be parsed for /

.

Perhaps the idea is not to create hacky expressions for the potentially complex syntax for hosts and mount points that some systems might have to design credentials.

If this is homework, I can give you an algorithm you should come up with, but it occurs to me that one way to meet these requirements is to try it by running mkdir the full path. If that fails, truncate the last directory and try again, if that fails, truncate another and try again ... Eventually you need to get to the root directory without understanding the server syntax and then you will need to start adding the component path back and creating subtitles one by one.

0


source


std::pair<bool, unsigned long> CreateDirectory(std::basic_string<_TCHAR> path)
{
    _ASSERT(!path.empty());
    typedef std::basic_string<_TCHAR> tstring;

    tstring::size_type pos = 0;

    while ((pos = path.find_first_of(_T("\\/"), pos + 1)) != tstring::npos)
    {
        ::CreateDirectory(path.substr(0, pos + 1).c_str(), nullptr);
    }

    if ((pos = path.find_first_of(_T("\\/"), path.length() - 1)) == tstring::npos)
    {
        path.append(_T("\\"));
    }

    ::CreateDirectory(path.c_str(), nullptr);

    return std::make_pair(
        ::GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES,
        ::GetLastError()
        );
}

      

0


source


void createFolders(const std::string &s, char delim) {
std::stringstream ss(s);
std::string item;
char combinedName[50]={'\0'};
while (std::getline(ss, item, delim)) { 
  sprintf(combinedName,"%s%s%c",combinedName,item.c_str(),delim);          
  cout<<combinedName<<endl;
  struct stat st = {0};
  if (stat(combinedName,&st)==-1)
   { 
            #if REDHAT
                     mkdir(combinedName,0777);
            #else
                      CreateDirectory(combinedName,NULL);
            #endif
    }
 }
}

      

0


source







All Articles