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