I am writing a class (based on a class library) that creates a RAMDisk, and every X minutes I need to backup the contents of the RAMDisk to a physical location due to volatility. It was suggested to use CopyFileEx, as apparently the .NET file copy methods do not work.
For some reason I am getting an Invalid Arguements error when trying to use CopyFileEx though. I am assuming that I can still use the rest of the .NET methods in this function, but could just use some help fixing/cleaning it up a bit.
public static void CopyDirectoryVSS(string sourcePath, string targetPath)
{
// Check if the target directory exists, if not, create it.
if (Directory.Exists(targetPath) == false)
{
Directory.CreateDirectory(targetPath);
}
// Copy each file into it’s new directory.
foreach (string dir in Directory.GetDirectories(sourcePath))
{
foreach (string file in Directory.GetFiles(dir, "*.*"))
{
Console.WriteLine(#"Copying {0}\{1}", targetPath, file);
CopyFileEx(file, Path.Combine(target, file), null, 0, 0, 0);
}
}
// Copy each subdirectory using recursion.
DirectoryInfo sourceDir = new DirectoryInfo(#sourcePath);
DirectoryInfo TargetDir = new DirectoryInfo(targetPath);
foreach (DirectoryInfo diSourceSubDir in sourceDir.GetDirectories())
{
DirectoryInfo nextTargetSubDir = TargetDir.CreateSubdirectory(diSourceSubDir.Name);
CopyDirectory(diSourceSubDir, nextTargetSubDir);
}
}
Check out the answer here: I'm guessing that copy solution would be cleaner and you're essentially doing the same thing:
Copying Files Recursively
Related
I have this project where I'm iterating recursively in some folders and copy them to a new directory.
In the 2nd level of folders (child folder) I have a txt file which I am reading. Now, when I read that file, I parse a string and I want to give that string to the parent folder and assign it as its name. So far I can only do for its File only, because there is accessible but when I try to do it for the parent folder, it doesn't recognize the variable (which of course, makes sense!)
EDIT: I commented the code so it will be a little bit clearer.
Now, Is there any way I can achieve this?
Here's my code:
static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
{
//accessing the directiories inse of Destionationed directory
DirectoryInfo[] dirs = dir.GetDirectories();
Directory.CreateDirectory(destinationDir);
if (recursive)
{
// reading every folder inside first parent folder
foreach (DirectoryInfo subDir in dirs)
{
//reading every folder inside the second folder
DirectoryInfo[] Subdirs = subDir.GetDirectories();
foreach (DirectoryInfo subDir2 in Subdirs)
{
//setting the new path where I want my new files to be stored.
string newDestinationDir = Path.Combine(destinationDir, subDir2.Name);
//Now, here its where I want to change the main folder's name, but the value must be taking from inside it's file.
CopyDirectory(subDir2.FullName, newDestinationDir, true);
FileInfo[] SubDirsFiles = subDir2.GetFiles();
foreach (FileInfo getFile in SubDirsFiles)
{
File.Copy(getFile.FullName, newDestinationFile + "_" + dictionary["XECM_DOC_TYPE"], true);
}
}
}
}
}
Note: I'm using Dictiony to story the data I read from file, and thats what I'm trying to pass to the parent folder, exclusively-to the CopyDirectory(subDir2.FullnName,NewDestinationDir+dictionary["XECM_DOC_TYPE"],true) but logically it can't recognize the dictionary part because it is declared and initialized inside the FileInfo part...
I hope I was clear enough.
I am trying to create a directory and subdirectories and copy files from on one location to another location. The following code works but it doesn't create a parent directory(10_new) if there are sub directories. I am trying to copy all the contents(including subdirectories) from "c:\\sourceLoc\\10" to "c:\\destLoc\\10_new" folder. If "10_new" doesn't exist then I should create this folder. Please assist.
string sourceLoc = "c:\\sourceLoc\\10";
string destLoc = "c:\\destLoc\\10_new";
foreach (string dirPath in Directory.GetDirectories(sourceLoc, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(sourceLoc, destLoc));
if (Directory.Exists(sourceLoc))
{
//Copy all the files
foreach (string newPath in Directory.GetFiles(sourceLoc, "*.*", SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(sourceLoc, destLoc));
}
}
From looking at your code, you never check for the existence of the parent folders. You jump to getting all the child folders first.
if (!Directory.Exists(#"C:\my\dir")) Directory.CreateDirectory(#"C:\my\dir");
Here is how to copy all files in a directory to another directory
This is taken from http://msdn.microsoft.com/en-us/library/cc148994.aspx
string sourcePath = "c:\\sourceLoc\\10";
string targetPath = "c:\\destLoc\\10_new";
string fileName = string.Empty;
string destFile = string.Empty;
// To copy all the files in one directory to another directory.
// Get the files in the source folder. (To recursively iterate through
// all subfolders under the current directory, see
// "How to: Iterate Through a Directory Tree.")
// Note: Check for target path was performed previously
// in this code example.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
else
{
Console.WriteLine("Source path does not exist!");
}
Recursive Directory/Sub-directory
public class RecursiveFileSearch
{
static System.Collections.Specialized.StringCollection log = new System.Collections.Specialized.StringCollection();
static void Main()
{
// Start with drives if you have to search the entire computer.
string[] drives = System.Environment.GetLogicalDrives();
foreach (string dr in drives)
{
System.IO.DriveInfo di = new System.IO.DriveInfo(dr);
// Here we skip the drive if it is not ready to be read. This
// is not necessarily the appropriate action in all scenarios.
if (!di.IsReady)
{
Console.WriteLine("The drive {0} could not be read", di.Name);
continue;
}
System.IO.DirectoryInfo rootDir = di.RootDirectory;
WalkDirectoryTree(rootDir);
}
// Write out all the files that could not be processed.
Console.WriteLine("Files with restricted access:");
foreach (string s in log)
{
Console.WriteLine(s);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key");
Console.ReadKey();
}
static void WalkDirectoryTree(System.IO.DirectoryInfo root)
{
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;
// First, process all the files directly under this folder
try
{
files = root.GetFiles("*.*");
}
// This is thrown if even one of the files requires permissions greater
// than the application provides.
catch (UnauthorizedAccessException e)
{
// This code just writes out the message and continues to recurse.
// You may decide to do something different here. For example, you
// can try to elevate your privileges and access the file again.
log.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
}
if (files != null)
{
foreach (System.IO.FileInfo fi in files)
{
// In this example, we only access the existing FileInfo object. If we
// want to open, delete or modify the file, then
// a try-catch block is required here to handle the case
// where the file has been deleted since the call to TraverseTree().
Console.WriteLine(fi.FullName);
}
// Now find all the subdirectories under this directory.
subDirs = root.GetDirectories();
foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
// Resursive call for each subdirectory.
WalkDirectoryTree(dirInfo);
}
}
}
}
Before doing File.Copy, check to make sure the folder exists. If it doesn't create it.
This function will check if a path exists, if it doesnt, it will create it. If it fails to create it, for what ever reason, it will return false. Otherwise, true.
Private Function checkDir(ByVal path As String) As Boolean
Dim dir As New DirectoryInfo(path)
Dim exist As Boolean = True
If Not dir.Exists Then
Try
dir.Create()
Catch ex As Exception
exist = False
End Try
End If
Return exist
End Function
Remember, all .Net languages compile down to the CLR (common language runtime) so it does not matter if this is in VB.Net or C#. A good way to convert between the two is: http://converter.telerik.com/
It is impossible to copy or move files with C# in windows 7.
It will instead create a file of zero bytes.
I am using C# to copy files from one directory to another directory.
I am using code from msdn but its pretty slow taking a minute or so to
copy a couple of gigs. It only takes seconds in explorer.
http://channel9.msdn.com/Forums/TechOff/257490-How-Copy-directories-in-C
Surly there a faster way..:)
private static void Copy(string sourceDirectory, string targetDirectory)
{
DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
CopyAll(diSource, diTarget);
}
private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
// 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())
{
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);
}
}
Using Parallel I was able to copy 6gigs in under a minute faster than explorer and xcopy.
private static void CopyAll(string SourcePath, string DestinationPath)
{
string[] directories = System.IO.Directory.GetDirectories(SourcePath, "*.*", SearchOption.AllDirectories);
Parallel.ForEach(directories, dirPath =>
{
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
});
string[] files = System.IO.Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories);
Parallel.ForEach(files, newPath =>
{
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath));
});
}
What u are using is recursion. It always slows the system.
Use this as it has no recursion.
void CopyAll (string SourcePath, string DestinationPath)
{
//Now 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));
}
Your issue is probabbly on *overwriteé of the file.
I see that you call
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
where true means overwrite the file if it exists.
Based on this I suppose so that it's a case in your app to overwrite already existing files.
The stuff should go faster if you
first rename destination directory with some temporary unique name
after just copy source to dest (so no overwrite)
if success remove temp directory, if fails remove all copied files and rename temp to its original name.
Should be faster.
Good luck.
I suspect #Oded is correct, and you're comparing a copy to a move.
If you want to ensure that what you're doing is the same as the shell does, you could look into SHFileOperation, or (on Vista or newer) IFileOperation. At least as far as I know, you'd have to use SHFileOperation via P/Invoke. IFileOperation is a COM interface.
There is a big problem with using Parallel.ForEach loops with creating directories, the first thing you need to be aware of, are sub directories nested within other directories, if Parallel creates directories out of order, the code can be thrown due to trying to create directory level 8 while directory level 6 was not even made yet.
I have an autoupdater C# program. It will download a rar file that holds the changed or new files for the update to some software. The rar file has it's structure just like the base directory of the software but only contains changed or new files/folders. Is there an easy way to "merge" these files/folders to the destination directory so in that if the file/folder exists already it'll be replaced and if not it'll be added or do I have to manually walk through each file/folder and do this myself? Just hoping there is a nice little merge function that .NET has :)
DirectoryInfo Class
The following example demonstrates how to copy a directory and its contents.
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);
}
}
The simplest way is to use the FileSystem.MoveDirectory method. Make sure you add a reference to the Microsoft.VisualBasic.dll:
using Microsoft.VisualBasic.FileIO;
...
// Merge D:\SourceDir with D:\DestDir:
FileSystem.MoveDirectory("D:\\SourceDir", "D:\\DestDir", true /* Overwrite */);
I need to Copy folder C:\FromFolder to C:\ToFolder
Below is code that will CUT my FromFolder and then will create my ToFolder.
So my FromFolder will be gone and all the items will be in the newly created folder called ToFolder
System.IO.Directory.Move(#"C:\FromFolder ", #"C:\ToFolder");
But i just want to Copy the files in FromFolder to ToFolder.
For some reason there is no System.IO.Directory.Copy???
How this is done using a batch file - Very easy
xcopy C:\FromFolder C:\ToFolder
Regards
Etienne
This link provides a nice example.
http://msdn.microsoft.com/en-us/library/cc148994.aspx
Here is a snippet
// To copy all the files in one directory to another directory.
// Get the files in the source folder. (To recursively iterate through
// all subfolders under the current directory, see
// "How to: Iterate Through a Directory Tree.")
// Note: Check for target path was performed previously
// in this code example.
if (System.IO.Directory.Exists(sourcePath))
{
string[] files = System.IO.Directory.GetFiles(sourcePath);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
// Use static Path methods to extract only the file name from the path.
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(targetPath, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
there is a file copy.
Recreate folder and copy all the files from original directory to the new one
example
static void Main(string[] args)
{
DirectoryInfo sourceDir = new DirectoryInfo("c:\\a");
DirectoryInfo destinationDir = new DirectoryInfo("c:\\b");
CopyDirectory(sourceDir, destinationDir);
}
static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination)
{
if (!destination.Exists)
{
destination.Create();
}
// Copy all files.
FileInfo[] files = source.GetFiles();
foreach (FileInfo file in files)
{
file.CopyTo(Path.Combine(destination.FullName,
file.Name));
}
// Process subdirectories.
DirectoryInfo[] dirs = source.GetDirectories();
foreach (DirectoryInfo dir in dirs)
{
// Get destination directory.
string destinationDir = Path.Combine(destination.FullName, dir.Name);
// Call CopyDirectory() recursively.
CopyDirectory(dir, new DirectoryInfo(destinationDir));
}
}
Copying directories (correctly) is actually a rather complex task especially if you take into account advanced filesystem techniques like junctions and hard links. Your best bet is to use an API that supports it. If you aren't afraid of a little P/Invoke, SHFileOperation in shell32 is your best bet. Another alternative would be to use the Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory method in the Microsoft.VisualBasic assembly (even if you aren't using VB).
yes you are right.
http://msdn.microsoft.com/en-us/library/system.io.directoryinfo.aspx
has provided copy function ..
or you can use another function
http://msdn.microsoft.com/en-us/library/ms127960.aspx
You'll need to create a new directory from scratch then loop through all the files in the source directory and copy them over.
string[] files = Directory.GetFiles(GlobalVariables.mstrReadsWellinPath);
foreach(string s in files)
{
fileName=Path.GetFileName(s);
destFile = Path.Combine(DestinationPath, fileName);
File.Copy(s, destFile);
}
I leave creating the destination directory to you :-)
You're right. There is no Directory.Copy method. It would be a very powerful method, but also a dangerous one, for the unsuspecting developer. Copying a folder can potentionaly be a very time consuming operation, while moving one (on the same drive) is not.
I guess Microsoft thought it would make sence to copy file by file, so you can then show some kind of progress information. You could iterate trough the files in a directory by creating an instance of DirectoryInfo and then calling GetFiles(). To also include subdirectories you can also call GetDirectories() and enumerate trough these with a recursive method.
A simple function that copies the entire contents of the source folder to the destination folder and creates the destination folder if it doesn't exist
class Utils
{
internal static void copy_dir(string source, string dest)
{
if (String.IsNullOrEmpty(source) || String.IsNullOrEmpty(dest)) return;
Directory.CreateDirectory(dest);
foreach (string fn in Directory.GetFiles(source))
{
File.Copy(fn, Path.Combine(dest, Path.GetFileName(fn)), true);
}
foreach (string dir_fn in Directory.GetDirectories(source))
{
copy_dir(dir_fn, Path.Combine(dest, Path.GetFileName(dir_fn)));
}
}
}
This article provides an alogirthm to copy recursively some folder and all its content
From the article :
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.
Good luck!
My version of DirectoryInfo.CopyTo using extension.
public static class DirectoryInfoEx {
public static void CopyTo(this DirectoryInfo source, DirectoryInfo target) {
if (source.FullName.ToLower() == target.FullName.ToLower())
return;
if (!target.Exists)
target.Create();
foreach (FileInfo f in source.GetFiles()) {
FileInfo newFile = new FileInfo(Path.Combine(target.FullName, f.Name));
f.CopyTo(newFile.FullName, true);
}
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) {
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
diSourceSubDir.CopyTo(nextTargetSubDir);
}
}
}
And use like that...
DirectoryInfo d = new DirectoryInfo("C:\Docs");
d.CopyTo(new DirectoryInfo("C:\New"));