Jul 09
Sadly there is no built-in function in System.IO that will copy a folder and its contents. Following is a simple recursive algorithm that copies a folder, its sub-folders and files, creating the destination folder if needed. For simplicity, there is no error handling; an exception will throw if anything goes wrong, such as null or invalid paths or if the destination files already exist.
using System; using System.IO; namespace CSharp411 { class Program { static void Main( string[] args ) { CopyFolder( @"C:temptest", @"C:tempout" ); Console.ReadLine(); } static public void CopyFolder( string sourceFolder, string destFolder ) { if (!Directory.Exists( destFolder )) Directory.CreateDirectory( destFolder ); string[] files = Directory.GetFiles( sourceFolder ); foreach (string file in files) { string name = Path.GetFileName( file ); string dest = Path.Combine( destFolder, name ); File.Copy( file, dest ); } string[] folders = Directory.GetDirectories( sourceFolder ); foreach (string folder in folders) { string name = Path.GetFileName( folder ); string dest = Path.Combine( destFolder, name ); CopyFolder( folder, dest ); } } } }
That helps too much.
Thank you
thanks, it was very helpful, i was wondering if it works as a windows application
Thanks!
great help. very good example explained in simple and easy way thanks
I would push them on to a stack and process the stack in a while loop than call the function recursively. Good example.
Thanks a lot for publishing this code it merely completed my whole project scope
It works perfectly.
Thanks a lot…
It should be easier if Microsoft provided us ways to copy subdirectories… ;D ;D ;D
what I am doing is to use Start method from the Process class from System.Diagnostics namespace
Process.Start(, );
using xcopy.exe inside windowssystem32
e.g.: xcopy /E
;D ;D ;D
It should be easier if Microsoft provided us ways to copy subdirectories… ;D ;D ;D
what I am doing is to use Start method from the Process class from System.Diagnostics namespace
Process.Start(-program name-, -arguments-);
using xcopy.exe inside windowssystem32
e.g.: xcopy -sourcedirectory- -targetdirectory- /E
;D ;D ;D
Thanks……….
It helped me alot…….
Thanks a lot.
It works very nicely in windows mobile too.
Thanks alot.. It was awesome..
Thanks man, exactly what I needed 🙂
thanks, its such a nice things
What about
if a file already exist at destination folder ???
-Thanks,
Best Regards
Thanks, a lot,
Good Stuf
Thanks You Sir superb 100 % working code..
🙂
Thanks for the pretty simple and nice example!
What if your copying a directory to its sub-directory?
This algorithm works fine if there is no parent-child relation between the source and destination directory.
If you pass a subdirectory as destination directory this algorithm doesn’t take care of it. It will endlessly enumerate the newly created sub folders and makes further copies of them.
If you pass a parent directory of source as destination the following happens: If the directory structure has any element which on the new destination path collides with the root of the source structure there will be undesired happenings: Overwrites or unsuccessful copies because of colliding filenames or duplicated copies.
I’ll implement such procedure which get over these problems so this function basically right but have to be a little extended for my needs.
I wrote this using Linq (I don’t like recursive functions):
public static void CopyAllFiles(string sourceFolder, string destinationFolder)
{
var FileList = from files in Directory.GetFiles(sourceFolder, “*.*”, SearchOption.AllDirectories)
select files;
foreach (string file in FileList)
{
string RelativeFilePath = file.Replace(sourceFolder, “”);
string DestinationFilePath = String.Format(“{0}{1}{2}”,
destinationFolder, Path.DirectorySeparatorChar, RelativeFilePath);
if (!Directory.Exists(Path.GetDirectoryName(DestinationFilePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(DestinationFilePath));
}
File.Copy(file, DestinationFilePath, true);
}
}
This creates only readonly files and directories even if the destination directory is read-write,
how can I change to read-write all the permissions on this copied files and directories?
this creates a new readonly directory and files,
what if I want them to be read-write?
Thx
Great very helpful
to Enrique: you can remove read-only flag on some files or directories by using this
staticvoid setAttributesNormal(DirectoryInfo dir)
{
// Remove flags from the current directory
dir.Attributes = FileAttributes.Normal;
// Remove flags from all files in the current directory
foreach (FileInfo file in dir.GetFiles())
{
file.Attributes = FileAttributes.Normal;
}
// Do the same for all subdirectories
foreach (DirectoryInfo subDir in dir.GetDirectories())
{
setAttributesNormal(subDir);
}
}
ref : http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx
@Eitan… great solution, thanks! I noticed that it will not copy directories that are empty. Any way to get around that?
You have two options, one is to use Directory.GetFileSystemEntries(,), and copy or create directory according to the entry type (this function returns files and folders as well).
The other option is to do first a loop for folders only by using Directory.GetDirectories(), and create the target folder if it does not exist, if you use this approach, you can remove the folder creation from the file loop.
Many thanks….you saved my day
you can check this post:
http://namita2021.wordpress.com/2010/05/07/system-io-directory-2/
Works great !!!
Here is my version of the above, and its recursive.
http://01792.org/blog/post/2010/10/06/Recursive-file-and-folder-copy.aspx
Helped me very much.
But I want more something…
I want to replace any file who already exists…
is there anybody who can help me..?
@Andre: Use this overload of the Copy method:
File.Copy( source, dest, overwrite );
it´s just this???
when i pass overwrite like third argument
the name ‘overwrite’ does not exist in the current context
yeah
it´s just this
it works very well
thanks man
This is refactored safe version
http://01792.org/blog/post/2010/10/06/Recursive-file-and-folder-copy.aspx
In 4 lines
Hi Eitan,
I tried your code. Its fail when i have empty folder inside the sub directory. otherwise I didn’t see any performance improvements
Here is an improved version, which copies also empty folders:
public static void CopyAllFiles(string sourceFolder, string destinationFolder)
{
foreach (string directory in Directory.GetDirectories(sourceFolder, “*”, SearchOption.AllDirectories))
{
string DestinationFilePath = String.Format(“{0}{1}{2}”,
destinationFolder, Path.DirectorySeparatorChar, directory.Replace(sourceFolder, “”));
if (!Directory.Exists(DestinationFilePath))
Directory.CreateDirectory(DestinationFilePath);
foreach (string file in Directory.GetFiles(directory, “*”, SearchOption.TopDirectoryOnly))
{
File.Copy(file, Path.Combine(DestinationFilePath, Path.GetFileName(file)), true);
}
}
}
I don’t think that there are performance differences between the recursive or iterative versions, the bottleneck is the copy itself. I just don’t like recursion. In order to lower copy times, you will need 1) go to a lower level (maybe file streams at byte level), and/or 2) multi-threaded copy (the new parallel framework in .NET 4 might help here, although I haven’t tried it, yet)
Thanks Eitan.
I tried the Parallel framework in .NET 4 and updated my code is here. It will give better performance.
private void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
foreach (DirectoryInfo dir in source.GetDirectories())
{
DirectoryInfo targetSubDirectory = target.CreateSubdirectory(dir.Name);
CopyFilesRecursively(dir, targetSubDirectory);
}
Parallel.ForEach(source.GetFiles(),
filePath =>
{
System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
filePath.CopyTo(Path.Combine(target.FullName, filePath.Name));
});
});
}
Works like a charm. Thanks!
protected void fnCopyDirFile(string SourcePath, string DestinPath)
{
try
{
top:
DirectoryInfo SourceFile = new DirectoryInfo(SourcePath);
DirectoryInfo DestinFile = new DirectoryInfo(DestinPath);
if (!File.Exists(DestinPath))
{
Directory.CreateDirectory(DestinPath);
}
DirectoryInfo[] SrcFle = SourceFile.GetDirectories();
DirectoryInfo[] DstFle = DestinFile.GetDirectories();
List SrcLst = new List();
List DstLst = new List();
foreach (DirectoryInfo d1 in SrcFle)
{
SrcLst.Add(d1);
}
foreach (DirectoryInfo d2 in DstFle)
{
DstLst.Add(d2);
}
int cnt;
cnt = 0;
for (int a = 0; a < SrcFle.Length; a++)
{
if (DstFle.Length == 0)
{
Directory.CreateDirectory(DestinPath + SrcFle[a].Name);
goto top;
}
cnt = 0;
for (int b = 0; b < DstFle.Length; b++)
{
if (SrcLst[a].Name == DstLst[b].Name)
{
cnt++;
}
}
if (cnt == 0)
{
Directory.CreateDirectory(DestinPath + SrcLst[a].Name);
StreamWriter sw;
sw = new StreamWriter(@"c:LockFile@Folder" + System.DateTime.Now.ToString("dd-MMM-yyyy") + ".txt", true);
sw.WriteLine(z + " " + " Folder Created:" + " " + SrcLst[a].Name);
sw.WriteLine();
sw.Close();
z++;
}
fnCopyDirFile(SourcePath + SrcLst[a].Name + @"", DestinPath + SrcLst[a].Name + @"");
}
}
catch (Exception ex)
{
Console.Write(ex.Message.ToString());
}
}
It was very helpful to me..Thanks alot…
Why take all this pain?
Simply use a VB function: Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory
Add a reference of Microsoft.VisualBasic to your .Net assembly. MS does not stop us from doing so.
Hope this helps somebody out there.
Aarkay, that is true. But this code is helpful when one wants a more custom method, such as in my case. I need to copy using a filter. I only want to copy, let’s say, *.doc files. Now I can use this method as a starting point to create my method.
If you dont want to copy hidden files/folders, here is the mod:
private void copyFolder(string sourceFolder, string destFolder)
{
// First check if directory exists
if (!Directory.Exists(destFolder))
Directory.CreateDirectory(destFolder);
// Get all files in this folder (Except Hidden)
var files = new DirectoryInfo(sourceFolder).GetFiles().Where(x => (x.Attributes & FileAttributes.Hidden) == 0);
// Process each file in this folder
foreach (FileInfo file in files)
{
string name = file.Name;
string dest = Path.Combine(destFolder, name);
File.Copy(file.FullName, dest);
}
// Get all directories in this folder (Except Hidden)
var folders = new DirectoryInfo(sourceFolder).GetDirectories().Where(x => (x.Attributes & FileAttributes.Hidden) == 0);
// Process each subfolder in this folder
foreach (DirectoryInfo folder in folders)
{
string name = folder.Name;
string dest = Path.Combine(destFolder, name);
copyFolder(folder.FullName, dest);
}
}
Nice core code – very fast and I can easily expand from it. Thanks
Thank You very much!! Muchas gracias
Wow Very interesting. easy and effective. 🙂