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

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

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

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

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


当前回答

只是想加上我的版本。它可以处理目录和文件,如果目标文件存在,则可以覆盖或跳过。

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

其他回答

容易得多

private static void CopyFilesRecursively(string sourcePath, string targetPath)
{
    //Now Create all of the directories
    foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
    {
        Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
    }

    //Copy all the files & Replaces any files with the same name
    foreach (string newPath in Directory.GetFiles(sourcePath, "*.*",SearchOption.AllDirectories))
    {
        File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true);
    }
}

复制自MSDN:

using System;
using System.IO;

class CopyDir
{
    public static void Copy(string sourceDirectory, string targetDirectory)
    {
        DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
        DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);

        CopyAll(diSource, diTarget);
    }

    public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
    {
        Directory.CreateDirectory(target.FullName);

        // Copy each file into the new directory.
        foreach (FileInfo fi in source.GetFiles())
        {
            Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
            fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
        }

        // Copy each subdirectory using recursion.
        foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
        {
            DirectoryInfo nextTargetSubDir =
                target.CreateSubdirectory(diSourceSubDir.Name);
            CopyAll(diSourceSubDir, nextTargetSubDir);
        }
    }

    public static void Main()
    {
        string sourceDirectory = @"c:\sourceDirectory";
        string targetDirectory = @"c:\targetDirectory";

        Copy(sourceDirectory, targetDirectory);
    }

    // Output will vary based on the contents of the source directory.
}

对于d4nt的答案有一个小的改进,因为如果你在服务器和开发机器上工作,你可能想检查错误,而不必更改xcopy路径:

public void CopyFolder(string source, string destination)
{
    string xcopyPath = Environment.GetEnvironmentVariable("WINDIR") + @"\System32\xcopy.exe";
    ProcessStartInfo info = new ProcessStartInfo(xcopyPath);
    info.UseShellExecute = false;
    info.RedirectStandardOutput = true;
    info.Arguments = string.Format("\"{0}\" \"{1}\" /E /I", source, destination);

    Process process = Process.Start(info);
    process.WaitForExit();
    string result = process.StandardOutput.ReadToEnd();

    if (process.ExitCode != 0)
    {
        // Or your own custom exception, or just return false if you prefer.
        throw new InvalidOperationException(string.Format("Failed to copy {0} to {1}: {2}", source, destination, result));
    }
}

使用这个类。

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

试试这个:

Process proc = new Process();
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "xcopy.exe");
proc.StartInfo.Arguments = @"C:\source C:\destination /E /I";
proc.Start();

你的xcopy参数可能会有所不同,但你知道的。