【问题标题】:How to copy more than one folder into another folder?如何将多个文件夹复制到另一个文件夹?
【发布时间】:2013-10-29 02:01:16
【问题描述】:

现在问题来了: 我有很多代码都做同样的事情。也就是说,它将两个文件夹的内容复制到一个目标文件夹中,并将它们合并到目标文件夹中。我的问题是,我找不到(经过大量谷歌搜索)如何实际复制源目录 + 内容,而不仅仅是其内容和子文件夹然后最终合并 .

这可能是我获取目录的方式:我使用文件夹选择对话框,将路径名添加到列表框(显示),然后从列表框中的项目创建(字符串)目录列表。

这是到目前为止的代码。 (部分来自 MSDN)

public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
    {
        if (source.FullName.ToLower() == target.FullName.ToLower())
        {
            return;
        }

        // Check if the target directory exists, if not, create it. 
        if (Directory.Exists(target.FullName) == false)
        {
            Directory.CreateDirectory(target.FullName);
        }

        // Copy each file into it's new directory. 
        foreach (FileInfo fi in source.GetFiles())
        {
            fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
        }

        // Copy each subdirectory using recursion. 
        foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
        {
            DirectoryInfo nextTargetSubDir =
                target.CreateSubdirectory(diSourceSubDir.Name);
            CopyAll(diSourceSubDir, nextTargetSubDir);
        }
    }
    //This is inside a button click Method

    List<string> pathList = new List<string>();
        pathList = lstBox.Items.Cast<String>().ToList();

        string sourceDirectory;
        string targetDirectory;

        DirectoryInfo dirSource;
        DirectoryInfo dirTarget;

        for (int i = 0 ; i < pathList.Count; i++)
        {
            sourceDirectory = pathList.ElementAt(i);
            targetDirectory = browserSave.SelectedPath; //browserSave is the Folder Selection Dialog
            dirSource = new DirectoryInfo(sourceDirectory);
            dirTarget = new DirectoryInfo(targetDirectory);

            CopyAll(dirSource, dirTarget);                
        }

令人讨厌的是,C# 没有 Directory.Copy 函数,这将是非常有用的。 回顾一下。

我选择文件夹 1。 我选择文件夹 2。 I 选择目标文件夹。 我按确定。 预期结果:目标文件夹有两个文件夹,文件夹 1 和文件夹 2 里面。两者都有里面的所有文件。 实际结果:目标文件夹合并了松散的文件,源文件夹的子目录完好无损。 (这很烦人)

我希望这些信息足以为您的专业人士提供帮助。

【问题讨论】:

  • 如果您的函数将两个 String 对象(源和目标路径)作为参数,则更简洁的方法是。在此处检查接受的答案:*.com/questions/1066674/…
  • 我做了更多的搜索,甚至添加了对 Visual Basic DLL 的引用——它有自己的 CopyDirectory() 方法。它做同样的问题。问题必须在于我如何获取源目录或其他东西。不确定...谢谢!
  • @Sizza - 是的,这就是你调用副本的方式 - 请参阅我的答案。

标签: c#


【解决方案1】:

而不是DirectoryInfo 传递string 作为参数。请参阅下面的代码。

private void DirectoryCopy(
    string sourceDirName, string destDirName, bool copySubDirs)
{
  DirectoryInfo dir = new DirectoryInfo(sourceDirName);
  DirectoryInfo[] dirs = dir.GetDirectories();

  // If the source directory does not exist, throw an exception.
    if (!dir.Exists)
    {
        throw new DirectoryNotFoundException(
            "Source directory does not exist or could not be found: "
            + sourceDirName);
    }

    // If the destination directory does not exist, create it.
    if (!Directory.Exists(destDirName))
    {
        Directory.CreateDirectory(destDirName);
    }


    // Get the file contents of the directory to copy.
    FileInfo[] files = dir.GetFiles();

    foreach (FileInfo file in files)
    {
        // Create the path to the new copy of the file.
        string temppath = Path.Combine(destDirName, file.Name);

        // Copy the file.
        file.CopyTo(temppath, false);
    }

    // If copySubDirs is true, copy the subdirectories.
    if (copySubDirs)
    {

        foreach (DirectoryInfo subdir in dirs)
        {
            // Create the subdirectory.
            string temppath = Path.Combine(destDirName, subdir.Name);

            // Copy the subdirectories.
            DirectoryCopy(subdir.FullName, temppath, copySubDirs);
        }
    }
}

在主函数中。

static void Main(string[] args)
    {

        List<string> directoryNames = new List<string>()  // For multiple source folders
        {
            "C:\\Folder1", "C:\\Folder2"
        };

        string destDirName = "C:\\Folder3";
        foreach (string sourceDirName in directoryNames)
        {
            DirectoryCopy(sourceDirName, destDirName, true)
        }
    }

【讨论】:

  • 我已经使用了这个代码。它将所有源目录、子目录和文件复制到目标文件夹中。问题究竟出在哪里?
  • 我了解代码有效,我需要它做的是将源文件夹 + 内容复制到我选择的新文件夹中。正如我刚刚尝试过的那样,这段代码的作用是将源文件夹的内容复制到目标文件夹中。这里的问题是当我选择多个要复制的文件夹时,它会将它们合并,我想在其中保留树结构。
  • 您要复制多个文件夹意味着您的源文件夹不止一个。对吗??
  • 我已针对多个源目录更新了我的问题
  • 谢谢,Hogan 已经解决了。我很欣赏你的工作,并同意字符串可能更简洁。
【解决方案2】:

问题是您永远不会为您的目标创建一个新目标——这将为循环的每次迭代创建一个与源同名的新目标,然后复制到该目标。

for (int i = 0 ; i < pathList.Count; i++)
{
   sourceDirectory = pathList.ElementAt(i);
   targetDirectory = browserSave.SelectedPath; //browserSave is the Folder Selection Dialog
   dirSource = new DirectoryInfo(sourceDirectory);

   string targetPath = target.Fullname+
                  Path.DirectorySeparatorChar+
                  sourceDirectory.Split(Path.DirectorySeparatorChar).Last());

   Directory.CreateDirectory(targetPath);

   dirTarget = new DirectoryInfo(targetPath);

   CopyAll(dirSource, dirTarget);                
 }

警告我没有测试,所以我可能有错别字,但你明白了。

【讨论】:

  • 啊哈,我就是这么想的。我认为这可能是发布后的问题。谢谢,我现在去测试一下。
  • 对,所以我在按钮方法中对此进行了测试。它什么也不做。 (这在某种程度上是进步)。也许我需要在复制方法本身中创建新目标?
  • @Sizza - 这确实创建了目标......就在它说创建目录的地方 - 在调试器中运行并查看变量是什么。也许没有设置 browserSave.SelectedPath?
  • 编辑没关系,我不小心将 FullName 更改为 Name。它的工作原理
【解决方案3】:

这将帮助您解决问题。此函数是一个通用递归函数,用于复制文件夹与或不合并子文件夹。

public static void DirectoryCopy(string sourceDirPath, string destDirName, bool isCopySubDirs)
{
    // Get the subdirectories for the specified directory.
    DirectoryInfo directoryInfo = new DirectoryInfo(sourceDirPath);
    DirectoryInfo[] directories = directoryInfo.GetDirectories();
    if (!directoryInfo.Exists)
    {
        throw new DirectoryNotFoundException("Source directory does not exist or could not be found: "
            + sourceDirPath);
    }
    DirectoryInfo parentDirectory = Directory.GetParent(directoryInfo.FullName);
    destDirName = System.IO.Path.Combine(parentDirectory.FullName, destDirName);

    // 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 = directoryInfo.GetFiles();

    foreach (FileInfo file in files)
    {
        string tempPath = System.IO.Path.Combine(destDirName, file.Name);

        if (File.Exists(tempPath))
        {
            File.Delete(tempPath);
        }

        file.CopyTo(tempPath, false);
    }
    // If copying subdirectories, copy them and their contents to new location using recursive  function. 
    if (isCopySubDirs)
    {
        foreach (DirectoryInfo item in directories)
        {
            string tempPath = System.IO.Path.Combine(destDirName, item.Name);
            DirectoryCopy(item.FullName, tempPath, isCopySubDirs);
        }
    }
}

【讨论】:

  • 复制程序不是问题
【解决方案4】:

试试下面的。当您调用操作时,您显然需要相应地设置源文件夹和目标文件夹。另外我建议您不要在事件处理程序中嵌入任何逻辑。 希望这会有所帮助。

            Action<string, string> action = null;
            action = (source,dest) =>
                {
                    if(Directory.Exists(source))
                    {
                        DirectoryInfo sInfo = new DirectoryInfo(source);
                        if (!Directory.Exists(dest))
                        {
                            Directory.CreateDirectory(dest);
                        }
                        Array.ForEach(sInfo.GetFiles("*"), a => File.Copy(a.FullName, Path.Combine(dest,a.Name)));
                        foreach (string dir in Directory.EnumerateDirectories(source))
                        {
                            string sSubDirPath = dir.Substring(source.Length+1,dir.Length-source.Length-1);
                            string dSubDirPath = Path.Combine(dest,sSubDirPath);
                            action(dir, dSubDirPath);
                        }
                    }
                };
            action(@"C:\source", @"C:\dest");

【讨论】: