开发者

How to compare two folders for similar files based on name in C#?

开发者 https://www.devze.com 2023-01-29 19:28 出处:网络
I have two folders A and B..Inside A multiple files are there and inside B multiple files are there..I have to check files in A with files in B for identical files...

I have two folders A and B..Inside A multiple files are there and inside B multiple files are there..I have to check files in A with files in B for identical files... I tried like this for a particular file name

void DirSe开发者_运维技巧arch(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);
                    }
       }

It is working..I tried like this for two folders

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

It is not working...Any suggestion??


If you're using .NET 4, you can use DirectoryInfo and EnumerateFiles(). Then you can use LINQ to join the two directories to get the common files between the two directories.

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;

or you can use where if you want additional conditions to apply.

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

These will both give you stream of strings. If you need the actual FileInfo instances, change the select part of the query to return f1 instead of f1.Name.

If you're using .NET 3.5, you need to use GetFiles() instead, which returns FileInfo[]. So the queries will look like this:

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

and

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


Why don't use just something like this (without recursion) ?

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

Of course this solution suffers a performance decay in case of many files, because Directory.GetFiles navigates all files even when you pass a restrictive pattern. To be more faster you could use LINQ as pointed out in Brian Rasmussen's answer

EDIT:
a faster example using 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;
}


try below code , you need to change path of files

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


What you are basically doing is:

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.

The first one works because;

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

Tell us what you need and maybe we can help..


Maybe compare (for a non-linq version) --

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

精彩评论

暂无评论...
验证码 换一张
取 消