Today I had the task of copying a directory recursively in C#. The first thing I did was type into my project “Directory.” and see if intellisense brought up a function called Directory.Copy. Unfortunately there is not a Directory.Copy, which to me seems like an oversight, as copying a directory is fairly common. Maybe it is not an action commonly done in C#.
So next I went to my browser and did a search. Well, I am not the first, nor will I be the last to solve this. There are a number of solutions online and each seem to have both positive and negative comments.
Option 1 – A directory copy using recursion
Pros: This is simple and to the point and elegant.
Cons: One complaint is that this could cause a stack overly by using recursion but this might not be a valid con as the filesystem restrictions in Windows might prevent a stack overflow anyway.
Since I am dealing with a small controlled tree, the con will not affect me., but since we are dealing with a file system, this is likely not to occur.
private static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
foreach (DirectoryInfo dir in source.GetDirectories())
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
foreach (FileInfo file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name));
}
Option 2 – Use SearchOption.AllDirectories to create the directory structure then then copy all the files
Pros: Does not use recursion
Cons: Are there any?
private static void CopyFilesRecursively(String SourcePath, String DestinationPath)
{
// First create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
// Copy all the files
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath));
}
Option 3 – Use one of the methods recommended by MSDN
Unfortunately MSDN is not consistent, and recommends two different methods in two different places, which I am sure were written by different teams.
using System;
using System.IO;
class DirectoryCopyExample
{
static void Main()
{
DirectoryCopy(".", @".\temp", true);
}
private static void DirectoryCopy(
string sourceDirName, string destDirName, bool copySubDirs)
{
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
DirectoryInfo[] dirs = dir.GetDirectories();
// If the source directory does not exist, throw an exception.
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
// If the destination directory does not exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the file contents of the directory to copy.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
// Create the path to the new copy of the file.
string temppath = Path.Combine(destDirName, file.Name);
// Copy the file.
file.CopyTo(temppath, false);
}
// If copySubDirs is true, copy the subdirectories.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
// Create the subdirectory.
string temppath = Path.Combine(destDirName, subdir.Name);
// Copy the subdirectories.
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
}
Or the different one they posted here:
using System;
using System.IO;
class CopyDir
{
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
if (source.FullName.ToLower() == target.FullName.ToLower())
{
return;
}
// Check if the target directory exists, if not, create it.
if (Directory.Exists(target.FullName) == false)
{
Directory.CreateDirectory(target.FullName);
}
// Copy each file into it's new directory.
foreach (FileInfo fi in source.GetFiles())
{
Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
public static void Main()
{
string sourceDirectory = @"c:\sourceDirectory";
string targetDirectory = @"c:\targetDirectory";
DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
CopyAll(diSource, diTarget);
}
// Output will vary based on the contents of the source directory.
}
Option 4 – Use Microsoft.VisualBasic
Pros: One line.
Cons: You have to reference an additional dll that you otherwise do not need.
This additional dll is not available in Mono for cross-platform development.
new Microsoft.VisualBasic.Devices.Computer().
FileSystem.CopyDirectory( sourceFolder, outputFolder );
There are various other methods:
Resources:
http://stackoverflow.com/questions/58744/best-way-to-copy-the-entire-contents-of-a-directory-in-c
http://msdn.microsoft.com/en-us/library/system.io.directoryinfo.aspx
http://msdn.microsoft.com/en-us/library/bb762914.aspx
http://xneuron.wordpress.com/2007/04/12/copy-directory-and-its-content-to-another-directory-in-c/
http://www.logiclabz.com/c/copy-directory-in-net-c-including-sub-folders.aspx