views:

407

answers:

6

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), and creates directories as necessary so that the whole path is created.

I am attempting a pretty naive implementation of this myself and it seems to be a string processing nightmare. There is / vs \, there is the special case of network shares which begin with \\ (also you can't attempt to mkdir() the first two levels of the path which are machine name and share name), and there is \.\ type nonsense that can exist in a path.

Does there exist a simple way to do this in C++?

+1  A: 

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.

Aamir
+2  A: 

Try STLSoft's winstl::create_directory_recurse().

dcw
+3  A: 

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).

Frerich Raabe
A: 

From http://www.cplusplus.com/reference/string/string/find%5Flast%5Fof/:

// 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.

kitchen
+1  A: 

Use Boost::filesystem

this link will help you :) http://www.boost.org/doc/libs/1%5F40%5F0/libs/filesystem/doc/index.htm

Davit Siradeghyan
A: 

You can use good old mkdir for that. Just run

system("mkdir " + strPath);

and you're done.

Well, almost. There are still cases you have to take care of, such as network shares (which might not work) and backslashes. But when using relatively safe paths, you can use this shorter form.

Another thing you might find useful getting rid of the possible nuisance is _fullpath(), which will resolve the given path into a full and clean one. Knowing you have a clean path, you should have no problem writing a rather trivial recursive function that will create the folders one by one, even when dealing with UNC paths.

eran
I'm not proud of it but this was the solution we went for. Very short, works for network shares.. Just too easy to ignore.
pauldoo
(also no dependency on shell32..)
pauldoo
Well, if it makes you feel better, all the path formatting and recursive creation has been implemented in mkdir. So in principle, it's like using boost, winstl or any other 3rd party solution...
eran