我想用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 );
这似乎是一个相当丑陋的黑客。有没有更好的办法?
当前回答
tboswell的替换证明版本(这是弹性的重复模式在文件路径)
public static void copyAll(string SourcePath , string DestinationPath )
{
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(Path.Combine(DestinationPath ,dirPath.Remove(0, SourcePath.Length )) );
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
File.Copy(newPath, Path.Combine(DestinationPath , newPath.Remove(0, SourcePath.Length)) , true);
}
其他回答
下面是一个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 class Extensions
{
public static void CopyTo(this DirectoryInfo source, DirectoryInfo target, bool overwiteFiles = true)
{
if (!source.Exists) return;
if (!target.Exists) target.Create();
Parallel.ForEach(source.GetDirectories(), (sourceChildDirectory) =>
CopyTo(sourceChildDirectory, new DirectoryInfo(Path.Combine(target.FullName, sourceChildDirectory.Name))));
foreach (var sourceFile in source.GetFiles())
sourceFile.CopyTo(Path.Combine(target.FullName, sourceFile.Name), overwiteFiles);
}
public static void CopyTo(this DirectoryInfo source, string target, bool overwiteFiles = true)
{
CopyTo(source, new DirectoryInfo(target), overwiteFiles);
}
}
如果您喜欢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;
}
对于UWP和Winui 3 (WindowsAppSdk)使用Async API:
public async Task CopyAsync(StorageFolder source, StorageFolder dest)
{
foreach (var item in await source.GetItemsAsync())
if (item is StorageFile file)
await file.CopyAsync(dest);
else if (item is StorageFolder folder)
await CopyAsync(folder, await dest.CreateFolderAsync(folder.Name, CreationCollisionOption.OpenIfExists));
}
只是想加上我的版本。它可以处理目录和文件,如果目标文件存在,则可以覆盖或跳过。
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);
}
}