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.
public static void DeepCopy(DirectoryInfo source, DirectoryInfo target)
{
foreach (DirectoryInfo dir in source.GetDirectories())
DeepCopy(dir, target.CreateSubdirectory(dir.Name));
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!
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).
public static void CopyDirectory(
string sourceDirectoryName,
string destinationDirectoryName
)
and you can use it like this, for example:
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:
public static void DeepCopy(DirectoryInfo source, DirectoryInfo target, string excludePattern)
{
foreach (DirectoryInfo dir in source.GetDirectories())
{
Match match = Regex.Match(dir.Name, excludePattern);
if (!match.Success)
DeepCopy(dir, target.CreateSubdirectory(dir.Name), excludePattern);
}
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.
public static void DeepCopy(DirectoryInfo source, DirectoryInfo target)
{
foreach (DirectoryInfo dir in source.GetDirectories())
{
DirectoryInfo SubDir = target.CreateSubdirectory(dir.Name)
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:
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