The problem of comparing two directories

I am trying to compare two directories to see which files are in directory 1, which are not in directory 2. I have the following code:

System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA); System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB); IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.PRN"); IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.PRN"); IEnumerable<System.IO.FileInfo> list3 = list1.Except(list2); Console.WriteLine("The following files are in list1 but not list2:"); foreach (var v in list3) { Console.WriteLine(v); } Console.WriteLine("Press any key to continue..."); Console.ReadKey(); 

When this is done, it clearly lists all the files that are in directory 1, but many of them are already in directory 2. I can see this simply by looking at Windows Explorer and looking at the file names. What am I missing?

EDIT:

I believe the problem is in the file comparison section. I am trying to make it ignore the case of a file extension. I tried this:

  class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo> { public FileCompare() { } public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2) { //return (f1.Name.ToUpper == f2.Name.ToUpper && // f1.Length == f2.Length); return (string.Equals(f1.Name, f2.Name, StringComparison.OrdinalIgnoreCase) && f1.Length == f2.Length); } public int GetHashCode(System.IO.FileInfo fi) { string s = String.Format("{0}{1}", fi.Name, fi.Length); return s.GetHashCode(); } } 

But that still doesn't work. You can see that I commented on another attempt to simply make all uppercase in comparison, but that is not the case.

+4
source share
4 answers

You will need to use the overloaded version of Except() and pass it the custom implementation of IEqualityComparer , which accurately indicates your criteria for determining the exact match of the two FileInfo objects.

See an example here and modify its own needs: http://msdn.microsoft.com/en-us/library/bb336390.aspx

+7
source

Here is an MSDN example that shows you how to do this.

Create an IEqualityComparer

 class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo> { public FileCompare() { } public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2) { return (f1.Name == f2.Name && f1.Length == f2.Length); } public int GetHashCode(System.IO.FileInfo fi) { string s = String.Format("{0}{1}", fi.Name, fi.Length); return s.GetHashCode(); } } 

Then use the Except overload with your comparator.

 var queryList1Only = (from file in list1 select file).Except(list2, myFileCompare); 
+2
source

You can use LINQ

  var list3 = from c in list1 where !(from o in list2 select o.Name) .Contains(c.Name) select c; 

There may also be a problem of different cases.

You can try

 .Equals(c.Name, StringComparison.OrdinalIgnoreCase) 

Instead

 .Contains(c.Name) 

Or translate everything to lowercase before comparison.

0
source

Since you are only interested in names, project your sequences onto name sequences using the .Select LINQ extension method:

 IEnumerable<string> list1 = dir1.GetFiles("*.PRN").Select(fi => fi.Name); IEnumerable<string> list2 = dir2.GetFiles("*.PRN").Select(fi => fi.Name); IEnumerable<string> list3 = list1.Except(list2); 

(You can use var , implicit typing.)

This is due to the fact that the default comparative for string has an ordinal and case-sensitive comparison (and not just comparison of link comparisons, for example, with the FileInfo class).

0
source

Source: https://habr.com/ru/post/1479813/


All Articles