如何递归地将整个目录复制并粘贴到新路径?

4
我想将一个目录作为复制/粘贴例程移动,保持其结构不变。我不仅要查找目录中所有子文件夹中的文件,然后将它们复制/粘贴(如解决方案),而是要克隆整个目录并保持其结构不变(树->子文件夹和文件),就像复制和粘贴例程一样。
所以我找到了这个函数,可以将一个包含文件的文件夹复制到新路径:

文件夹->文件(s)

该函数的行为与复制/粘贴例程相同。它需要SourcePath、DestinationPath和布尔值OverWriteExisting。非常好而且小,但很遗憾它没有被标记为那个问题的实际答案(建议评分)。
但是如果我想移动整个目录怎么办?换句话说,如果我有一个包含文件夹的文件夹,每个文件夹下面可能还有更多的文件夹和文件等等,而且也许不知道文件结构树的大小,像这样:

文件夹 -> 文件夹(们) -> ... -> 文件夹(们) -> 文件(们)

我正在使用以下例程来复制/粘贴具有文件夹的文件夹。 但是在这里,我知道我只有一个层次的文件夹,所以只需要一个foreach循环:
foreach (var Folder in DestinationFolder) // here I know that I have only one level of folders to reach the files
{
    CopyDirectory(FolderPath, DestinationPath, false); // use that function to copy the files
}

这个函数对以下目录结构起作用:
文件夹 -> 文件夹(们) -> 文件(们)
我尝试了 this 但没有得到想要的结果。它只检索所有文件,而不是搜索所有子文件夹。这不是我想要的。我想保留子文件夹和原始结构。在这里,我得到了四个文件,而不是像原来的目录结构一样,包括子文件夹、子文件夹中的子文件夹、子文件夹和文件。只有四个文件,因为它删除了重复项,但我不希望这种情况发生,因为我需要全部的文件。
以下是我的当前结构(但我的问题适用于任何目录):
文件夹 -> 文件夹 -> 文件夹+文件
以下是下面代码在新路径上的操作:
NewFolder -> 所有子文件夹中找到的所有文件
dialog.FileName = dialog.FileName.Replace(".xml", ""); // get the destination path
DirectoryInfo dirInfo = new DirectoryInfo(dialog.FileName);

if (dirInfo.Exists == false)
    Directory.CreateDirectory(dialog.FileName);

List<String> EverythingInTheDirectory = Directory
                    .GetFiles(FileStructure.baseSessionPath + "\\" + SelectedSession.Name, "*.*", SearchOption.AllDirectories).ToList(); // source

foreach (string file in EverythingInTheDirectory)
{
    FileInfo mFile = new FileInfo(file);
    // to remove name collusion
    if (new FileInfo(dirInfo + "\\" + mFile.Name).Exists == false)
        mFile.MoveTo(dirInfo + "\\" + mFile.Name);
}

如何移动整个目录并保持其结构不变?而不是只获取目录中的文件并将它们移动!这个目录的大小未知。

在这个上下文中,“clone”是什么意思,它与递归地复制目录到另一个位置有何不同?同时,请粘贴一些代码。你尝试过什么? - Zuzlx
你的相关问题已经有两个重新开启投票。耐心等待,给它一些时间来重新开启,而不是发布实际上的重复帖子。这不是一个“即时满足”的网站;你不会立刻得到答案,如果你一遍又一遍地发布它,也不会有所帮助。 - Ken White
人们确实会去那里。有一个审查队列,这就是你得到两个重新开放投票的原因。而你告诉Zuxlx“看看‘问题’,你就会看到我尝试过什么”,这表明你已经知道这是一个重复的问题。(还要澄清一点,“复制/粘贴”是用户在Windows资源管理器中执行的操作。编程解决方案不会“复制/粘贴”;代码会创建目录并复制文件。) - Ken White
复制问题以链接到原始问题是不正确的行为。你应该做的是编辑原始问题以改进它,这将使其重新出现在问题列表的顶部,引起注意,并迅速重新打开它。(这正是[帮助]所说的,你应该这样做。)现在你应该编辑这个问题,包括你其他问题中的代码和细节,然后删除那个问题以消除混乱。 - Ken White
2个回答

20
这里有一个示例,可以将一个目录递归地克隆到另一个目标目录。
class Program
{
    static void Main(string[] args)
    {
        CloneDirectory(@"C:\SomeRoot", @"C:\SomeOtherRoot");
    }

    private static void CloneDirectory(string root, string dest)
    {
        foreach (var directory in Directory.GetDirectories(root))
        {
            //Get the path of the new directory
            var newDirectory = Path.Combine(dest, Path.GetFileName(directory));
            //Create the directory if it doesn't already exist
            Directory.CreateDirectory(newDirectory);
            //Recursively clone the directory
            CloneDirectory(directory, newDirectory);
        }

        foreach (var file in Directory.GetFiles(root))
        {
            File.Copy(file, Path.Combine(dest, Path.GetFileName(file)));
        }
    }
}

2
这正是我要找的。它完全做到了我想要的。它将一个文件夹复制并粘贴到一个新路径中。谢谢! - Khalil Khalaf
我也是。虽然现代的 .net 仍然对文件系统操作处理得有点荒谬 :-) - Xan-Kun Clark-Davis
@hawkstrider 我根据你的方法做了一些变化。再次感谢。 - Xan-Kun Clark-Davis
3
如果目录已经存在,Directory.CreateDirectory 操作将不会生效,因此在执行 Directory.CreateDirectory 之前不需要先使用 Directory.Exists 进行判断。 - Etienne de Martel

1
@hawkstrider的代码略有不同。
private static void CloneDirectory(DirectoryInfo source, DirectoryInfo dest) {
    foreach (var source_subdir in source.EnumerateDirectories()) {
        var target_subdir = new DirectoryInfo(Path.Combine(dest.FullName, source_subdir.Name));
        target_subdir.Create();
        CloneDirectory(source_subdir, target_subdir);
    }

    foreach (var source_file in source.EnumerateFiles()) {
        var target_file = new FileInfo(Path.Combine(dest.FullName, source_file.Name));
        source_file.CopyTo(target_file.FullName, true);
    }
}

编辑:
正如 @EtiennedeMartel 正确指出的那样,Create() 不需要进行 Exists 检查。 ms-docs
此外,枚举胜利!


1
如果目录已经存在,Create() 就是一个空操作,所以不需要进行 Exists 检查。当有大量文件需要处理时,你应该使用 EnumerateDirectories()EnumerateFiles() 来获得更好的性能(因为 GetDirectories()/GetFiles() 会分配数组)。 - Etienne de Martel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接