Options for copying a directory recursively with C#
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