168

Imagine I wish to create (or overwrite) the following file :- C:\Temp\Bar\Foo\Test.txt

Using the File.Create(..) method, this can do it.

BUT, if I don't have either one of the following folders (from that example path, above)

  • Temp
  • Bar
  • Foo

then I get an DirectoryNotFoundException thrown.

So .. given a path, how can we recursively create all the folders necessary to create the file .. for that path? If Temp or Bar folders exists, but Foo doesn't... then that is created also.

For simplicity, lets assume there's no Security concerns -- all permissions are fine, etc.

eddie
  • 1,252
  • 3
  • 15
  • 20
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • 1
    possible duplicate of [saving a file and automatically create directories](http://stackoverflow.com/questions/660685/saving-a-file-and-automatically-create-directories) – mateuscb Nov 03 '14 at 23:17
  • Possible duplicate of [If a folder does not exist, create it](http://stackoverflow.com/questions/9065598/if-a-folder-does-not-exist-create-it) – Michael Freidgeim Nov 28 '16 at 03:04

9 Answers9

183

To summarize what has been commented in other answers:

//path = @"C:\Temp\Bar\Foo\Test.txt";
Directory.CreateDirectory(Path.GetDirectoryName(path));

Directory.CreateDirectory will create the directories recursively and if the directory already exist it will return without an error.

If there happened to be a file Foo at C:\Temp\Bar\Foo an exception will be thrown.

hultqvist
  • 17,451
  • 15
  • 64
  • 101
  • If you are dealing with long path (256+) see https://stackoverflow.com/questions/5188527/how-to-deal-with-files-with-a-name-longer-than-259-characters – Alexei Levenkov Jan 01 '19 at 01:07
137
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.",
    Directory.GetCreationTime(path));

See this MSDN page.

starball
  • 20,030
  • 7
  • 43
  • 238
Christopher B. Adkins
  • 3,499
  • 2
  • 26
  • 29
  • 88
    You can blindly call `Directory.CreateDirectory` without the `Directory.Exists` check first - it won't throw if the directory is already there. – Tim Robinson Jul 08 '10 at 08:14
  • 1
    @Tim: Wasn't sure so I threw it in there anywho. Thanks for the info though. – Christopher B. Adkins Jul 08 '10 at 08:16
  • 27
    And don't forget about [`Path.GetDirectoryName(string path)`](http://msdn.microsoft.com/en-us/library/system.io.path.getdirectoryname.aspx) to get the directory from your full path – Oliver Jul 08 '10 at 08:21
  • @Oliver: There is a whole slew of functionality that goes along with the Directory and DirectoryInfo classes, but the code I gave was enough to give him a push in the right direction. I think the link also expands quite a bit. – Christopher B. Adkins Jul 08 '10 at 09:12
  • 10
    *NOTE: the variable `path` should not contain the file name. So using the OP's example `path` should be `C:\Temp\Bar\Foo`. After calling `Directory.CreateDirectory(path);` you still need to call `File.Create("C:\Temp\Bar\Foo\Test.txt");` to create the file. – sazr Jun 25 '14 at 05:45
  • This doesn't work as it would create also a directory with the file name. – Bartosz Wójtowicz Mar 03 '21 at 18:05
17

Use Directory.CreateDirectory before you create the file. It creates the folder recursively for you.

Grzenio
  • 35,875
  • 47
  • 158
  • 240
5

. given a path, how can we recursively create all the folders necessary to create the file .. for that path

Creates all directories and subdirectories as specified by path.

Directory.CreateDirectory(path);

then you may create a file.

Arseny
  • 7,251
  • 4
  • 37
  • 52
4

You will need to check both parts of the path (directory and filename) and create each if it does not exist.

Use File.Exists and Directory.Exists to find out whether they exist. Directory.CreateDirectory will create the whole path for you, so you only ever need to call that once if the directory does not exist, then simply create the file.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • For Directory.CreateDirectory you do not need to see which part exists. It will create all directories needed (only thing to make sure is that the targeted directory does not exists already). – Gertjan Jul 08 '10 at 08:02
  • I suggest removing the first line of you answer in that case since he doesn't need to check for each part from the root, just check the complete path and create it if it does not exist. – Gertjan Jul 08 '10 at 08:13
  • @Gertjan - answer updated... hope it meets your standards now ;) – Oded Jul 08 '10 at 08:18
  • :) it does :) (it was not my point to prove you wrong or to offend you, but beginners can use any clarification in the answers) – Gertjan Jul 08 '10 at 08:29
2

You should use Directory.CreateDirectory.

http://msdn.microsoft.com/en-us/library/54a0at6s.aspx

Nick
  • 4,787
  • 2
  • 18
  • 24
1

Assuming that your assembly/exe has FileIO permission is itself, well is not right. Your application may not run with admin rights. Its important to consider Code Access Security and requesting permissions Sample code:

FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, "C:\\test_r");
f2.AddPathList(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, "C:\\example\\out.txt");
try
{
    f2.Demand();
}
catch (SecurityException s)
{
    Console.WriteLine(s.Message);
}

Understanding .NET Code Access Security

Is “Code Access Security” of any real world use?

Community
  • 1
  • 1
PRR
  • 1,190
  • 7
  • 13
  • 2
    @Pure.Krome: Although my answer is off target, still do consider security and access control when accessing privileged resource. Never meant to overtake or complicate your question :) – PRR Jul 09 '10 at 05:15
0

You want Directory.CreateDirectory()

Here is a class I use (converted to C#) that if you pass it a source directory and a destination it will copy all of the files and sub-folders of that directory to your destination:

using System.IO;

public class copyTemplateFiles
{


public static bool Copy(string Source, string destination)
{

    try {

        string[] Files = null;

        if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
            destination += Path.DirectorySeparatorChar;
        }

        if (!Directory.Exists(destination)) {
            Directory.CreateDirectory(destination);
        }

        Files = Directory.GetFileSystemEntries(Source);
        foreach (string Element in Files) {
            // Sub directories
            if (Directory.Exists(Element)) {
                copyDirectory(Element, destination + Path.GetFileName(Element));
            } else {
                // Files in directory
                File.Copy(Element, destination + Path.GetFileName(Element), true);
            }
        }

    } catch (Exception ex) {
        return false;
    }

    return true;

}



private static void copyDirectory(string Source, string destination)
{
    string[] Files = null;

    if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
        destination += Path.DirectorySeparatorChar;
    }

    if (!Directory.Exists(destination)) {
        Directory.CreateDirectory(destination);
    }

    Files = Directory.GetFileSystemEntries(Source);
    foreach (string Element in Files) {
        // Sub directories
        if (Directory.Exists(Element)) {
            copyDirectory(Element, destination + Path.GetFileName(Element));
        } else {
            // Files in directory
            File.Copy(Element, destination + Path.GetFileName(Element), true);
        }
    }

}

}

Markive
  • 2,350
  • 2
  • 23
  • 26
0

Following code will create directories (if not exists) & then copy files.

// using System.IO;

// for ex. if you want to copy files from D:\A\ to D:\B\
foreach (var f in Directory.GetFiles(@"D:\A\", "*.*", SearchOption.AllDirectories))
{
    var fi =  new FileInfo(f);
    var di = new DirectoryInfo(fi.DirectoryName);

    // you can filter files here
    if (fi.Name.Contains("FILTER")
    {
        if (!Directory.Exists(di.FullName.Replace("A", "B"))
        {                       
            Directory.CreateDirectory(di.FullName.Replace("A", "B"));           
            File.Copy(fi.FullName, fi.FullName.Replace("A", "B"));
        }
    }
}
Mehdi Dehghani
  • 10,970
  • 6
  • 59
  • 64
  • It seems like the questioner wanted to create files rather than copy them. – Thomas Fritz Jan 31 '21 at 11:45
  • @ThomasFritz you are right, but still there some good info about working with files and folders in my answer, don't you think so? should I delete my answer? – Mehdi Dehghani Jan 31 '21 at 15:53
  • I don't think you have to delete your answer per se: While it may not answer the original question it is placed below a handful of answers which do just that. Instead, your answer serves as an introduction to a different topic, specifically how files are copied, which I don't mind a little variety among StackOverflow answers. What you can do - if you have the time - is to adjust the wording of your answer in a way so that it doesn't present itself like the most complete answer of them all, which I believe to be an overstatement. – Thomas Fritz Feb 01 '21 at 18:14