Tom D
Tom D

Reputation: 361

C# Compare Lists of files based on Name not returning full path

I'm writing a method that I want to be able to compare a file list from 2 different directories based on the file name, and then store all of the files that do not exist in the 2nd directory into a list to be used later (Most likely to create another method to copy/move those files).

Everything seems to be working properly until I look at the list of files (FilesRemaiing list) and try to get the full path of the files. It ends up pointing to my bin/debug path.

I believe this is because in my queries, I'm specifically querying the file.Name to compare, and not the file.FullName. The reason for this is because the FullName will return the path as well as the filename, which I can't use for my compare statement (var FilesRemaining = FileList1.Except(FileList2).ToList();).

So my question becomes, how do I compare 2 sets of files based on just the name, but then store the full path of the exception list to a 3rd list that I can use later for copying/moving?

Here's my method:

   public static List<string> CompareFiles(string ComparePath1, string ComparePath2)
    {
        List<string> FileList1 = new List<string>();
        List<string> FileList2 = new List<string>();
        List<string> CompareFileList = new List<string>();
        DirectoryInfo directory1 = new DirectoryInfo(ComparePath1);
        FileInfo[] files1 = directory1.GetFiles("*.*", SearchOption.TopDirectoryOnly);
        DirectoryInfo directory2 = new DirectoryInfo(ComparePath2);
        FileInfo[] files2 = directory2.GetFiles("*.*", SearchOption.TopDirectoryOnly);

        //Queries the given directory for filenames
        var query1 = from file in files1
                where (!file.Attributes.HasFlag(FileAttributes.Hidden))
                    select (file.Name);
        foreach (var file in query1)
        {
            FileList1.Add(file);
        }

        var query2 = from file in files2
                    where (!file.Attributes.HasFlag(FileAttributes.Hidden))
                    select (file.Name);
        foreach (var file in query2)
        {
            FileList2.Add(file);
        }

        var FilesRemaining = FileList1.Except(FileList2).ToList();

        foreach (var file in FilesRemaining)
        {
            string fullFile = Path.GetFullPath(file);
            CompareFileList.Add(fullFile);
            Console.WriteLine(fullFile);
        }

        return CompareFileList;

    }

Upvotes: 3

Views: 634

Answers (2)

Hemid Abbasov
Hemid Abbasov

Reputation: 175

class Program
{
    static void Main(string[] args)
    {
        foreach ( var f in CompareFiles(@"x:\tmp\dir_1", @"x:\tmp\dir_2") )
        {
            Console.WriteLine(f);
        }

        Console.ReadKey();
    }

    public static List<string> CompareFiles(string comparePath1, string comparePath2)
    {
        //Queries the given directory for filenames
        var fileList1 = (from file in new DirectoryInfo(comparePath1).GetFiles("*.*", SearchOption.TopDirectoryOnly)
                         where !file.Attributes.HasFlag(FileAttributes.Hidden)
                         select file.Name).ToList();

        var fileList2 = (from file in new DirectoryInfo(comparePath2).GetFiles("*.*", SearchOption.TopDirectoryOnly)
                         where !file.Attributes.HasFlag(FileAttributes.Hidden)
                         select file.Name).ToList();
        return fileList1.Except(fileList2)
                        .Select(file => Path.Combine(comparePath1, file))
                        .ToList();
    }
}

Upvotes: -1

rokkerboci
rokkerboci

Reputation: 1167

Using this, you can retain you FileInfo objects, and still compute the Except list using only their names.

//More efficient way to get your files.
IEnumerable<FileInfo> files1 = directory1
    .GetFiles("*.*", SearchOption.TopDirectoryOnly)
    .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden));
IEnumerable<FileInfo> files2 = directory2
    .GetFiles("*.*", SearchOption.TopDirectoryOnly)
    .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden));

//It uses the FileNameComparer class to compare to values.
IEnumerable<FileInfo> filesRemaining = files1.Except(files2, new FileNameComparer());

and here is the FileNameComparer class.

public class FileNameComparer : IEqualityComparer<FileInfo>
{
    public bool Equals(FileInfo x, FileInfo y)
    {
        //Here is where the magic is happening.
        return x.Name == y.Name;
    }

    //You need this too, altougt, I am not quite sure when it gets used.
    public int GetHashCode(FileInfo obj)
    {

        return obj.Name.GetHashCode();
    }
}

Upvotes: 4

Related Questions