如何根据C#中的名称比较两个类似文件的文件夹?

时间:2010-12-07 08:55:22

标签: c#

我有两个文件夹AB ..内部有多个文件,B里面有多个文件。我必须检查A中的文件和B中的文件以查找相同的文件。 .. 我尝试使用这个特定的文件名

void DirSearch(string sDir)
        {
          List<string> lstFilesFound = new List<string>();
                foreach (string d in Directory.GetDirectories(sDir))
                    {
                        foreach (string f in Directory.GetFiles(d,"MsBuild_Tracker.proj")
                           {
                                lstFilesFound.Add(f);
                           }
                            DirSearch(d);
                    }
       }

它正在工作..我试过两个文件夹

foreach (string d in Directory.GetDirectories(sDir))
                {
                    foreach (string f in Directory.GetDirectories(dDir))
                    {
                        foreach (string g in Directory.GetFiles(d, f))
                        {
                            lstFilesFound.Add(g);
                        }
                        DirSearch(d, f);
                    }
                }

它不起作用......有什么建议吗?

5 个答案:

答案 0 :(得分:8)

如果您使用的是。NET 4 ,则可以使用DirectoryInfoEnumerateFiles()。然后,您可以使用LINQ连接两个目录以获取两个目录之间的公共文件。

var dir1 = new DirectoryInfo(@"c:\temp1");
var dir2 = new DirectoryInfo(@"c:\temp2");

var filesinboth = from f1 in dir1.EnumerateFiles()
                  join f2 in dir2.EnumerateFiles() on f1.Name equals f2.Name
                  select f1.Name;

如果您想要应用其他条件,则可以使用where

var filesinboth = from f1 in dir1.EnumerateFiles()
                  from f2 in dir2.EnumerateFiles()
                  where f1.Name == f2.Name // and some other condition
                  select f1.Name;

这些都会为您提供string的流。如果您需要实际的FileInfo个实例,请将查询的select部分更改为f1而不是f1.Name

如果您使用的是 .NET 3.5 ,则需要使用GetFiles()代替FileInfo[]。因此查询将如下所示:

var filesinboth = from f1 in dir1.GetFiles()
                  join f2 in dir2.GetFiles() on f1.Name equals f2.Name
                  select f1.Name;

var filesinboth = from f1 in dir1.GetFiles()
                  from f2 in dir2.GetFiles()
                  where f1.Name == f2.Name // and some other condition
                  select f1.Name;

答案 1 :(得分:3)

为什么不使用这样的东西(没有递归)?

public static IEnumerable<string> GetMachingFiles(string pathA, string pathB)
{
    var matchingFiles = new HashSet<string>();

    var allAfiles = Directory.GetFiles(pathA, "*", SearchOption.AllDirectories);
    foreach (var file in allAfiles)
    {
        foreach (var mathcFile in Directory.GetFiles(pathB, Path.GetFileName(file), SearchOption.AllDirectories))
            matchingFiles.Add(mathcFile);
    }
    return matchingFiles;
}

当然,在许多文件的情况下,此解决方案会遭受性能下降,因为即使您传递限制性模式,Directory.GetFiles也会导航所有文件。 为了更快,您可以使用Brian Rasmussen's answer

中指出的LINQ

修改
使用LINQ(.NET 3.5)的更快的例子:

public static IEnumerable<string> GetMachingFilesFast(string pathA, string pathB)
{
    DirectoryInfo dirA = new DirectoryInfo(pathA);
    DirectoryInfo dirB = new DirectoryInfo(pathB);

    var filesA = dirA.GetFiles("*",SearchOption.AllDirectories);
    var filesB = dirB.GetFiles("*", SearchOption.AllDirectories);

    var matchingFiles = 
    filesA.Where(fA => filesB.Any(
                                  fB => fA.Name == fB.Name 
                                  // && fA.LastWriteTime == fB.LastWriteTime
                                 )
                 )
          .Select(x => x.Name);
    return matchingFiles;
}

答案 2 :(得分:2)

尝试以下代码,您需要更改文件路径

   DirectoryInfo dinfoTemp1 = new DirectoryInfo(@"C:\\Temp1");
        DirectoryInfo dinfoTemp2 = new DirectoryInfo(@"C:\\Temp2");

        FileInfo[] lstTemp1 = dinfoTemp1.GetFiles();

     List<string> ui  =   lstTemp1.Where(
                          x => dinfoTemp2.GetFiles().
                          Where(y => y.Name.Contains(x.Name)).Count() > 0).
                          Select(x=>x.Name).ToList();

答案 3 :(得分:1)

你基本上做的是:

setting directory to var d like C://
Setting directory to var f like My Documents
Getting files that have the name My Documents in C://
and if you find any which I highly doubt, you add it to your list.

第一个起作用是因为;

sets the directory to var d like C://
gets the file that is named MsBuild_Tracker.proj in C://
adds it to the list.

告诉我们您的需求,也许我们可以提供帮助..

答案 4 :(得分:1)

也许比较(对于非linq版本) -

namespace RecursiveDirCompare
{
    class Program
    {
        static List initialFiles = new List();

        static string initRoot = @"root";
        static string initCompare = @"compare";

        static void Main(string[] args)
        {
            Directory.SetCurrentDirectory( @"C:\Temp\test\");
            initRoot = @"root";// args[0];
            initCompare = @"compare";// args[1];

            AddFilesToInitialList(initRoot);

            CompareWithInitialList(initCompare);

            Console.ReadKey();
        }

        static void AddFilesToInitialList(string root)
        {
            foreach (string file in Directory.GetFiles(root))
            {
                initialFiles.Add(file.Replace(initRoot, ""));
            }
            foreach (string directory in Directory.GetDirectories(root))
            {
                AddFilesToInitialList(directory);
            }
        }

        static void CompareWithInitialList(string root)
        {
            foreach (string file in Directory.GetFiles(root))
            {
                if(initialFiles.Contains(file.Replace(initCompare, "")))
                {
                    Console.WriteLine(file + " is found in both");
                }
            }
            foreach (string directory in Directory.GetDirectories(root))
            {
                CompareWithInitialList(directory);
            }            
        }
    }
}