In .NET, there is no built-in way to copy the entire contents of a directory including subfolders and their content. In this article, we will explore a clean, platform-agnostic solution for this operation. Additionally, we will see how we can implement this in the context of our projects seamlessly.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

How to Copy a Directory Contents to Another Directory?

First, let’s review how we want to approach the problem before we code. Since we are trying to do a deep copy of a directory we want to make sure all directories exist before we copy files. Then we are free to copy all files from the source path to the destination path.

We start by creating a directory at the destinationDir path for each directory and sub-directory under the sourceDir path. Note that GetDirectories() returns sub-directories only because we specified  SearchOption.AllDirectories and a wildcard search pattern *.

Now, let’s take a look at how we can implement this:

var allDirectories = Directory.GetDirectories(sourceDir, "*", SearchOption.AllDirectories)

foreach (string dir in allDirectories) 
{ 
    string dirToCreate = dir.Replace(sourceDir, destinationDir); 
    Directory.CreateDirectory(dirToCreate); 
}

Now that all directories are created, we can copy all files in all directories. Similarly, GetFiles() returns all files in all directories because we specified SearchOption.AllDirectories and a file wild card search pattern *.*:

var allFiles = Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories);

foreach (string newPath in allFiles) 
{
    File.Copy(newPath, newPath.Replace(sourceDir, destinationDir), overwriteFiles); 
} 

This solution is safe to run even if a directory or file already exists at the target location. Furthermore, by setting the overwriteFiles parameter we can indicate to File.Copy() if you want to overwrite files that already exist.

Lastly, let’s explore SearchOptions enum. In this solution, we are using AllDirectories since we want to copy all content under the sourceDir . The other option is SearchOption.TopDirectoryOnly which indicates operations should only occur under sourceDir and no other child directory.

Copy a Directory as DirectoryInfo Class Extension Method

In this section, we will add DeepCopy() as an extension method of the DirectoryInfo class. This is a great way to integrate the deep copy operation into a legacy .NET class already used to deal with directories.

Let’s start by creating a class with an extension method DeepCopy():

public static class DirectoryInfoExtensions 
{ 
    public static void DeepCopy(this DirectoryInfo directory, string destinationDir) 
    { 
        foreach (string dir in Directory.GetDirectories(directory.FullName, "*", SearchOption.AllDirectories)) 
        {
            string dirToCreate = dir.Replace(directory.FullName, destinationDir); 
            Directory.CreateDirectory(dirToCreate); 
        } 
            
        foreach (string newPath in Directory.GetFiles(directory.FullName, "*.*", SearchOption.AllDirectories)) 
        { 
            File.Copy(newPath, newPath.Replace(directory.FullName, destinationDir), true); 
        } 
    } 
}

Now we can import the namespace that contains our code and use the method:

var sourceDir = new DirectoryInfo(sourcePath);
sourceDir.DeepCopy(destinationPath, true);

Note that in this example of the solution we do not need the source directory path as a string in DeepCopy(). We can access this same value by referencing the DirectoryInfo.FullName property.

A Few Edge Cases to Consider

Let’s take a look at some common exceptions we may run into running this code.

First, we may see UnauthorizedAccessException this may occur during any file system operation on entries that have permission restrictions. Make sure the code is run as Administrator or the current user is given permissions to the sourceDir or destinationDir to avoid permission exceptions.

Next, let’s consider IOException. IOException may occur when the path passed to a function is a file when a directory path was expected.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

Lastly, DirectoryNotFoundException may occur when the path passed to a function does not exist or is an invalid path. Checking paths with Directory.Exists() or File.Exists() can avoid getting these exceptions.

Of course, these are not the only exceptions that can happen and you need to check your own code for other possible edge cases.

Conclusion

In this short article, we’ve learned how to copy a directory content to another directory. We can take this solution and apply it in many different contexts to improve our file management. Additionally, we can integrate it easily, using extension methods, into a currently existing class in our codebase that’s already doing some file management operations.