C# FileInfo - 查找重复文件

4
我有一个包含约200,000个文件条目的FileInfo数组。我需要找到所有具有相同文件名的文件。我需要从每个重复的文件中得到目录名称和文件名,因为我之后想要重新命名它们。
我已经尝试过以下方法:
- 使用两个For循环将每个条目与整个列表进行比较 // 不好的想法,这将需要数小时甚至数天^^ - 尝试使用Linq排序 // 因为我以前没有使用过Linq,所以我很难编写正确的语句,也许有人可以帮助我 :)
2个回答

11

听起来这样应该可以:

var duplicateNames = files.GroupBy(file => file.Name)
                          .Where(group => group.Count() > 1)
                          .Select(group => group.Key);

现在是学习 LINQ 的非常好的时机。它非常有用 - 学习它所花费的时间(即使只是LINQ to Objects)将非常快速地回报。

编辑:好吧,如果你想要每个组的原始FileInfo,只需删除select:

var duplicateGroups = files.GroupBy(file => file.Name)
                           .Where(group => group.Count() > 1);

// Replace with what you want to do
foreach (var group in duplicateGroups)
{
     Console.WriteLine("Files with name {0}", group.Key);
     foreach (var file in group)
     {
         Console.WriteLine("  {0}", file.FullName);
     }
}

我的错,你的解决方案非常好,但我忘了提到我需要知道每个重复文件的目录名称+文件名,因为我想要重命名它们 :) 抱歉和谢谢。 - The_Holy_One
太棒了,我已经知道LINQ有时可以非常方便,但我从未想象过它会如此出色。如果可以问一下,你有任何喜欢的学习LINQ的网页吗? - The_Holy_One
@user1168998:不是很确定,但你可以在MSDN上查找。 - Jon Skeet

2
这应该可以运行:
HashSet<string> fileNamesSet = new HashSet<string>();
List<string> duplicates = new List<string>();

foreach(string fileName in fileNames)
{
    if(fileNamesSet.Contains(fileName))
    {
        duplicates.Add(fileName);
    }
    else
    {
        fileNamesSet.Add(fileName);
    }
}

然后,重复项将包含所有重复文件名的列表。

请注意,由于Windows文件名不区分大小写,您可能希望通过首先使用.ToUpperInvariant()将所有文件名转换为大写来考虑这一点。


1
你不需要先进行Contains检查 - 你可以直接调用fileNamesSet.Add(fileName)并检查返回值,对于重复项它将会是false。 - Jon Skeet
我认为这样意图更加清晰 - 即使没有了解 HashSet<t> 类,含义也应该很明显。 - sga101
个人而言,我更愿意只了解我使用的API :) (对于一组添加方法返回是否实际进行更改非常普遍 - 这不是特别“隐藏”的信息。)你会在字典中使用ContainsKey然后使用索引器,而不是TryGetValue吗? - Jon Skeet
明白了,我可以直接放一个注释。 - sga101

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接