Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Folder [Directory] Deep Copy (including sub directories) in .NET

4.00/5 (10 votes)
4 Jul 2013CPOL3 min read 220.1K  
Copy a folder [i.e. directory] including subfolders and files (recursively)

Introduction

Ever needed to copy folder A to location B including sub-directories & files? Sounds fairly simple but, here's the thing - there's no deep copy of a folder in .NET ... (it's actually not entirely true, as I will illustrate below).

Background

I'd like to show some example methods of doing so, just to save you those "couple of minutes" of implementation, and to provide best practice, fault avoidance and various approaches of implementation.

Using the Code

First, the most "clean" and simple approach:

Note: This approach is using recursion, so for a massive folder tree, you might encounter a StackOverflow exception thrown.

C#
public static void DeepCopy(DirectoryInfo source, DirectoryInfo target)
{

    // Recursively call the DeepCopy Method for each Directory
    foreach (DirectoryInfo dir in source.GetDirectories())
        DeepCopy(dir, target.CreateSubdirectory(dir.Name));

    // Go ahead and copy each file in "source" to the "target" directory
    foreach (FileInfo file in source.GetFiles())
        file.CopyTo(Path.Combine(target.FullName, file.Name));

}  

Now this code is the basic to "copy & paste" to your Util class.

Important: There may be an ancestry logical flaw you should check and alert the method caller: You should avoid trying to copy C:\root to C:\root\child since the root folder will endlessly grow as a result of the copy itself!

C#
if (target.FullName.Contains(source.FullName))
    throw new exception("Cannot perform DeepCopy: Ancestry conflict detected");  

I've mentioned in the introduction section that there's actually a way to do this in .NET.

You can use the function FileSystem.CopyDirectory: (VB only).

* I'm not sure if they check for the ancestry conflict (but it's just one line of code to test it and I leave to you as homework).

C#
// Note that this is a function from the namespace Microsoft.VisualBasic.FileIO
// Assembly: Microsoft.VisualBasic (in Microsoft.VisualBasic.dll)
public static void CopyDirectory(
    string sourceDirectoryName,
    string destinationDirectoryName
) 

and you can use it like this, for example:

C#
// in VB.NET
My.Computer.FileSystem.CopyDirectory(source , target ,True)

The above use will replace source and target with the path and name of the directory you wish to copy and the location to which you wish to copy it.

Some Others Things You May Wish to Perform

Now, not always do you wish to copy the whole folders with every file in it.

You may wish to, for example copy the whole folder, but to exclude folders or files that answer to some criteria, in which case you add a RegularExpression filter.

The most simple extension to the first implementation would be:

C#
// This method uses Regular Expressions
// So you'll need to add 'using System.Text.RegularExpressions;'
public static void DeepCopy(DirectoryInfo source, DirectoryInfo target, string excludePattern)
{
    // Go through the Directories and recursively call the DeepCopy Method for each one
    foreach (DirectoryInfo dir in source.GetDirectories())
    {
        Match match = Regex.Match(dir.Name, excludePattern);
 
        if (!match.Success)
            DeepCopy(dir, target.CreateSubdirectory(dir.Name), excludePattern);
    }
 
    // Go ahead and copy each file to the target directory
    foreach (FileInfo file in source.GetFiles())
    {
        Match match = Regex.Match(file.Name, excludePattern);
 
        if (!match.Success)
            file.CopyTo(Path.Combine(target.FullName, file.Name)); 
    }
}

Copy the Directory Security As Well As the Content

As a tip request I received in a great comment, let's add another feature:

Copy the NTFS Access Control of folder Source to folder Target, let's give it a shot.

C#
// You'll need to add using 'System.Security.AccessControl' for this code
public static void DeepCopy(DirectoryInfo source, DirectoryInfo target)
{
    foreach (DirectoryInfo dir in source.GetDirectories())
    {
        DirectoryInfo SubDir = target.CreateSubdirectory(dir.Name)
    

        // --- IMPROVED SECTION ---
        // Set the security settings for the new directory same as the source dir
        SubDir.SetAccessControl( 
            new DirectorySecurity(dir.FullPath, AccessControlSections.All));
    

        DeepCopy(dir, SubDir);
    }
     
    foreach (FileInfo file in source.GetFiles())
        file.CopyTo(Path.Combine(target.FullName, file.Name));
 
}   

Using XCOPY- An Altogether Different Approach

Of course, there's always the down to earth approach to achieve things that the world does not want to let me do the "right way".

And I mean to use a process that does the work for you with good'ol XCopy.

Check out this following sample:

C#
// add using System.Diagnostics;
Process process = new Process();
process.StartInfo.FileName = "xcopy";
process.StartInfo.Arguments = @"c:\source c:\destination /e /h /c /I";
process.Start();  

When you copy or move files and folders by using Windows Explorer, the permissions that are set on the files or folders may change. For example, when you copy a file in an NTFS file system volume or between two NTFS volumes, Windows 2000 treats it as a new file. As a new file, it takes on the permissions of the destination folder, and you become the CREATOR OWNER.

Note: You must have Write permission for the destination folder to copy files and folders. You can use the XCopy command with the /O/X/E/H/K switches to copy the files and retain the existing permissions that have been specifically applied to the file or files.

These switches have the following effects:

  • /E - Copies folders and subfolders, including empty ones
  • /H - Copies hidden and system files also
  • /K - Copies attributes. Typically, Xcopy resets read-only attributes
  • /O - Copies file ownership and ACL information

/X - Copies file audit settings (implies /O).

I think you get the picture, if you are older than XXX [varies with time] years and have actually worked outside the Visual Studio environment [yes, some developers actually have never].

Sum Up

I'd appreciate any suggestions and/or other thoughts you may have to this issue.

Cheers, Edo

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)