C# 在将文件夹复制到自己的文件夹时,避免自定义的复制目录函数进行无限循环

C# 在将文件夹复制到自己的文件夹时,避免自定义的复制目录函数进行无限循环,c#,foreach,directory,.net,file-copying,C#,Foreach,Directory,.net,File Copying,我正在尝试此功能,它可以将文件夹中的所有文件以及包含文件的相关子文件夹复制到其他位置: using System.IO; private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting) { bool ret = true; try { S

我正在尝试此功能,它可以将文件夹中的所有文件以及包含文件的相关子文件夹复制到其他位置:

using System.IO;

 private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)
        {
            bool ret = true;
            try
            {
                SourcePath = SourcePath.EndsWith(@"\") ? SourcePath : SourcePath + @"\";
                DestinationPath = DestinationPath.EndsWith(@"\") ? DestinationPath : DestinationPath + @"\";

                if (Directory.Exists(SourcePath))
                {
                    if (Directory.Exists(DestinationPath) == false)
                        Directory.CreateDirectory(DestinationPath);

                    foreach (string fls in Directory.GetFiles(SourcePath))
                    {
                        FileInfo flinfo = new FileInfo(fls);
                        flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting);
                    }

                    foreach (string drs in Directory.GetDirectories(SourcePath))
                    {
                        DirectoryInfo drinfo = new DirectoryInfo(drs);
                        if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false || drs.Substring(drs.Length-8) == "archive")
                            ret = false;
                    }
                }
                else
                {
                    ret = false;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1} {2}", e.Message, Environment.NewLine + Environment.NewLine, e.StackTrace);
                ret = false;
            }
            return ret;
        }
在您必须将文件夹复制到另一个位置之前,它一直运行良好,但当您必须在自身中创建文件夹时(在我的示例中,我正在创建一个名为“存档”的子文件夹以跟踪上一次文件夹文件的更改),它会无限循环运行,因为它会在Directory.GetDirectories foreach循环中不断重新扫描自身,查找新创建的子文件夹并不断嵌套同一子文件夹,直到它达到“路径名太长,最多260个字符限制异常”

我试图通过使用条件来避免它

||drs.Substring(drs.Length-8)=“存档”)

它应该检查目录名,但似乎不起作用

我认为,不同的解决方案,如放置最大子文件夹深度扫描(即最大2个子文件夹),这样它就不会继续重新扫描所有嵌套文件夹,但我在目录对象中找不到这样的属性

我无法将整个内容复制到临时文件夹中,然后再复制到真实文件夹中,因为下次我扫描它时,它也会重新扫描存档文件夹

我想把所有的目录列表放在一个目录对象的ArrayList中,或许我可以检查像DirName之类的东西,但我不知道是否存在这样的属性


有什么解决方案吗?

这是一种递归不起作用的情况,因为目录和文件的列表在复制时总是发生变化。更好的解决方案是提前获取所有文件和文件夹的列表

您可以使用和将SearchOption设置为的方式获取树中的所有文件和目录。它们将分别返回所有文件和所有目录

您可以按照以下步骤复制文件:

  • 获取所有源目录的列表并按升序排序。这将确保父目录出现在其子目录之前
  • 通过按排序顺序创建子目录来创建目标目录结构。由于排序顺序确保始终在创建子文件夹之前创建父文件夹,因此不会出现任何路径冲突
  • 像以前一样将所有源文件复制到目标目录。由于目标目录结构已经存在,因此顺序在这一点上并不重要
  • 一个简单的例子:

        static void Main(string[] args)
        {
            var sourcePath = @"c:\MyRoot\TestFolder\";
    
            var targetPath = @"c:\MyRoot\TestFolder\Archive\";
    
            var directories=Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories);
            var files = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories);
    
            if(!Directory.Exists(targetPath))
                Directory.CreateDirectory(targetPath);
    
            foreach (var directory in directories)
            {
                var relativePath = GetRelativePath(sourcePath, directory);
                var toPath = Path.Combine(targetPath, relativePath);
                if (!Directory.Exists(toPath))
                {
                    Directory.CreateDirectory(toPath);
                }
            }
    
            foreach (var file in files)
            {
                var relativePath = GetRelativePath(sourcePath, file);
                var toPath = Path.Combine(targetPath, relativePath);
                if (!File.Exists(toPath))
                    File.Copy(file,toPath);
            }
        }
    
        //This is a very quick and dirty way to get the relative path, only for demo purposes etc
        private static string GetRelativePath(string rootPath, string fullPath)
        {
            return Path.GetFullPath(fullPath).Substring(rootPath.Length);
        }
    

    在子字符串之前已经尝试过,没有运气。即使比较从调试器获取的精确字符串值也不会产生任何结果。