我想用c#将一个目录的全部内容从一个位置复制到另一个位置。

使用System似乎没有办法做到这一点。没有大量递归的IO类。

如果我们添加对Microsoft的引用,VB中有一个方法可以使用。VisualBasic:

new Microsoft.VisualBasic.Devices.Computer().
    FileSystem.CopyDirectory( sourceFolder, outputFolder );

这似乎是一个相当丑陋的黑客。有没有更好的办法?


当前回答

下面的代码复制所有文件从源到目标给定的模式在相同的文件夹结构:

public static void Copy()
        {
            string sourceDir = @"C:\test\source\";
            string destination = @"C:\test\destination\";

            string[] textFiles = Directory.GetFiles(sourceDir, "*.txt", SearchOption.AllDirectories);

            foreach (string textFile in textFiles)
            {
                string fileName = textFile.Substring(sourceDir.Length);
                string directoryPath = Path.Combine(destination, Path.GetDirectoryName(fileName));
                if (!Directory.Exists(directoryPath))
                    Directory.CreateDirectory(directoryPath);

                File.Copy(textFile, Path.Combine(directoryPath, Path.GetFileName(textFile)), true);
            }
        }

其他回答

复制并替换文件夹中的所有文件

        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);
            }
    }

这里有一个简洁而有效的解决方案:

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);

如果您喜欢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;
}

一个只有一个循环复制所有文件夹和文件的变体:

foreach (var f in Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories))
{
    var output = Regex.Replace(f, @"^" + path, newPath);
    if (File.Exists(f)) File.Copy(f, output, true);
    else Directory.CreateDirectory(output);
}

你可以一直使用这个,摘自微软网站。

static void Main()
{
    // Copy from the current directory, include subdirectories.
    DirectoryCopy(".", @".\temp", true);
}

private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
    // Get the subdirectories for the specified directory.
    DirectoryInfo dir = new DirectoryInfo(sourceDirName);

    if (!dir.Exists)
    {
        throw new DirectoryNotFoundException(
            "Source directory does not exist or could not be found: "
            + sourceDirName);
    }

    DirectoryInfo[] dirs = dir.GetDirectories();
    // If the destination directory doesn't exist, create it.
    if (!Directory.Exists(destDirName))
    {
        Directory.CreateDirectory(destDirName);
    }

    // Get the files in the directory and copy them to the new location.
    FileInfo[] files = dir.GetFiles();
    foreach (FileInfo file in files)
    {
        string temppath = Path.Combine(destDirName, file.Name);
        file.CopyTo(temppath, false);
    }

    // If copying subdirectories, copy them and their contents to new location.
    if (copySubDirs)
    {
        foreach (DirectoryInfo subdir in dirs)
        {
            string temppath = Path.Combine(destDirName, subdir.Name);
            DirectoryCopy(subdir.FullName, temppath, copySubDirs);
        }
    }
}