我想用c#将一个目录的全部内容从一个位置复制到另一个位置。
使用System似乎没有办法做到这一点。没有大量递归的IO类。
如果我们添加对Microsoft的引用,VB中有一个方法可以使用。VisualBasic:
new Microsoft.VisualBasic.Devices.Computer().
FileSystem.CopyDirectory( sourceFolder, outputFolder );
这似乎是一个相当丑陋的黑客。有没有更好的办法?
我想用c#将一个目录的全部内容从一个位置复制到另一个位置。
使用System似乎没有办法做到这一点。没有大量递归的IO类。
如果我们添加对Microsoft的引用,VB中有一个方法可以使用。VisualBasic:
new Microsoft.VisualBasic.Devices.Computer().
FileSystem.CopyDirectory( sourceFolder, outputFolder );
这似乎是一个相当丑陋的黑客。有没有更好的办法?
当前回答
public static class Extensions
{
public static void Copy(this DirectoryInfo self, DirectoryInfo destination, bool recursively)
{
foreach (var file in self.GetFiles())
{
file.CopyTo(Path.Combine(destination.FullName, file.Name));
}
if (recursively)
{
foreach (var directory in self.GetDirectories())
{
directory.Copy(destination.CreateSubdirectory(directory.Name), recursively);
}
}
}
}
使用示例:
var sourceDirectory = new DirectoryInfo(@"C:\source");
var destinationDirectory = new DirectoryInfo(@"C:\destination");
if (destinationDirectory.Exists == false)
{
sourceDirectory.Copy(destinationDirectory, recursively: true);
}
其他回答
我的解决方案基本上是对@Termininja的答案的修改,但我增强了一点,它似乎比公认的答案快5倍以上。
public static void CopyEntireDirectory(string path, string newPath)
{
Parallel.ForEach(Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories)
,(fileName) =>
{
string output = Regex.Replace(fileName, "^" + Regex.Escape(path), newPath);
if (File.Exists(fileName))
{
Directory.CreateDirectory(Path.GetDirectoryName(output));
File.Copy(fileName, output, true);
}
else
Directory.CreateDirectory(output);
});
}
编辑:将@Ahmed Sabry修改为完全并行foreach确实会产生更好的结果,但是代码使用递归函数,在某些情况下并不理想。
public static void CopyEntireDirectory(DirectoryInfo source, DirectoryInfo target, bool overwiteFiles = true)
{
if (!source.Exists) return;
if (!target.Exists) target.Create();
Parallel.ForEach(source.GetDirectories(), (sourceChildDirectory) =>
CopyEntireDirectory(sourceChildDirectory, new DirectoryInfo(Path.Combine(target.FullName, sourceChildDirectory.Name))));
Parallel.ForEach(source.GetFiles(), sourceFile =>
sourceFile.CopyTo(Path.Combine(target.FullName, sourceFile.Name), overwiteFiles));
}
下面是一个DirectoryInfo的扩展方法。CopyTo(注意overwrite参数):
public static DirectoryInfo CopyTo(this DirectoryInfo sourceDir, string destinationPath, bool overwrite = false)
{
var sourcePath = sourceDir.FullName;
var destination = new DirectoryInfo(destinationPath);
destination.Create();
foreach (var sourceSubDirPath in Directory.EnumerateDirectories(sourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(sourceSubDirPath.Replace(sourcePath, destinationPath));
foreach (var file in Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories))
File.Copy(file, file.Replace(sourcePath, destinationPath), overwrite);
return destination;
}
复制并替换文件夹中的所有文件
public static void CopyAndReplaceAll(string SourcePath, string DestinationPath, string backupPath)
{
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory($"{DestinationPath}{dirPath.Remove(0, SourcePath.Length)}");
Directory.CreateDirectory($"{backupPath}{dirPath.Remove(0, SourcePath.Length)}");
}
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
{
if (!File.Exists($"{ DestinationPath}{newPath.Remove(0, SourcePath.Length)}"))
File.Copy(newPath, $"{ DestinationPath}{newPath.Remove(0, SourcePath.Length)}");
else
File.Replace(newPath
, $"{ DestinationPath}{newPath.Remove(0, SourcePath.Length)}"
, $"{ backupPath}{newPath.Remove(0, SourcePath.Length)}", false);
}
}
抱歉之前的代码,它仍然有bug:((成为最快枪问题的猎物)。这里是测试和工作。键是SearchOption。AllDirectories,这消除了显式递归的需要。
string path = "C:\\a";
string[] dirs = Directory.GetDirectories(path, "*.*", SearchOption.AllDirectories);
string newpath = "C:\\x";
try
{
Directory.CreateDirectory(newpath);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
for (int j = 0; j < dirs.Length; j++)
{
try
{
Directory.CreateDirectory(dirs[j].Replace(path, newpath));
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
string[] files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
for (int j = 0; j < files.Length; j++)
{
try
{
File.Copy(files[j], files[j].Replace(path, newpath));
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
比任何代码都好(使用递归扩展DirectoryInfo的方法)
public static bool CopyTo(this DirectoryInfo source, string destination)
{
try
{
foreach (string dirPath in Directory.GetDirectories(source.FullName))
{
var newDirPath = dirPath.Replace(source.FullName, destination);
Directory.CreateDirectory(newDirPath);
new DirectoryInfo(dirPath).CopyTo(newDirPath);
}
//Copy all the files & Replaces any files with the same name
foreach (string filePath in Directory.GetFiles(source.FullName))
{
File.Copy(filePath, filePath.Replace(source.FullName,destination), true);
}
return true;
}
catch (IOException exp)
{
return false;
}
}