我想用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 );
这似乎是一个相当丑陋的黑客。有没有更好的办法?
当前回答
如果您喜欢Konrad的流行答案,但希望源代码本身是目标文件夹下的一个文件夹,而不是将它的子文件夹放在目标文件夹下,下面是实现该目的的代码。它返回新创建的DirectoryInfo,这很方便:
public static DirectoryInfo CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
var newDirectoryInfo = target.CreateSubdirectory(source.Name);
foreach (var fileInfo in source.GetFiles())
fileInfo.CopyTo(Path.Combine(newDirectoryInfo.FullName, fileInfo.Name));
foreach (var childDirectoryInfo in source.GetDirectories())
CopyFilesRecursively(childDirectoryInfo, newDirectoryInfo);
return newDirectoryInfo;
}
其他回答
这里有一个简洁而有效的解决方案:
namespace System.IO {
public static class ExtensionMethods {
public static void CopyTo(this DirectoryInfo srcPath, string destPath) {
Directory.CreateDirectory(destPath);
Parallel.ForEach(srcPath.GetDirectories("*", SearchOption.AllDirectories),
srcInfo => Directory.CreateDirectory($"{destPath}{srcInfo.FullName[srcPath.FullName.Length..]}"));
Parallel.ForEach(srcPath.GetFiles("*", SearchOption.AllDirectories),
srcInfo => File.Copy(srcInfo.FullName, $"{destPath}{srcInfo.FullName[srcPath.FullName.Length..]}", true));
});
}
}
}
使用方法:
new DirectoryInfo(sourcePath).CopyTo(destinationPath);
或者,如果你想走一条艰难的路,为你的微软项目添加一个引用。然后使用下面的代码:
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(fromDirectory, toDirectory);
然而,使用一个递归函数是一个更好的方法,因为它不需要加载VB dll。
抱歉之前的代码,它仍然有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的扩展方法。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 Copy(
string source,
string destination,
string pattern = "*",
bool includeSubFolders = true,
bool overwrite = true,
bool overwriteOnlyIfSourceIsNewer = false)
{
if (File.Exists(source))
{
// Source is a file, copy and leave
CopyFile(source, destination);
return;
}
if (!Directory.Exists(source))
{
throw new DirectoryNotFoundException($"Source directory does not exists: `{source}`");
}
var files = Directory.GetFiles(
source,
pattern,
includeSubFolders ?
SearchOption.AllDirectories :
SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
var newFile = file.Replace(source, destination);
CopyFile(file, newFile, overwrite, overwriteOnlyIfSourceIsNewer);
}
}
private static void CopyFile(
string source,
string destination,
bool overwrite = true,
bool overwriteIfSourceIsNewer = false)
{
if (!overwrite && File.Exists(destination))
{
return;
}
if (overwriteIfSourceIsNewer && File.Exists(destination))
{
var sourceLastModified = File.GetLastWriteTimeUtc(source);
var destinationLastModified = File.GetLastWriteTimeUtc(destination);
if (sourceLastModified <= destinationLastModified)
{
return;
}
CreateDirectory(destination);
File.Copy(source, destination, overwrite);
return;
}
CreateDirectory(destination);
File.Copy(source, destination, overwrite);
}
private static void CreateDirectory(string filePath)
{
var targetDirectory = Path.GetDirectoryName(filePath);
if (targetDirectory != null && !Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}
}