2012-01-25 32 views
3

我有一個FileInfo陣列~200.000文件入口。我需要找到所有具有相同文件名的文件。我需要從每個重複文件中得到目錄名和文件名,因爲我想在之後重命名它們。C#FileInfo - 查找重複的文件

我已經嘗試過:

  • 比較整個列表中的每個條目與2 for「循環」 //壞主意,這將需要幾個小時甚至幾天^^
  • 嘗試使用LINQ的排序//因爲我沒有使用LINQ之前,我有困難寫正確的說法,也許有人可以幫我:)

回答

8

聽起來這應該這樣做:

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

現在將是一個非常適合學習LINQ的好時機。這非常有用 - 花時間學習(即使只是LINQ to Objects)也會很快恢復原狀。

編輯:好的,如果你想爲每個組原FileInfo,只是下降的選擇:

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

我的壞,你的解決方案就像魅力,但我forogt提到,我需要知道每個重複的文件的Directoy名稱+文件名,因爲我想重命名他們:)抱歉,謝謝。 –

+0

@ user1168998:編輯以顯示如何輕鬆完成此操作。 –

+0

非常好,我已經知道LINQ有時候會變得非常方便,但我從來沒有想到它會很棒。如果我可以問,你有沒有最喜歡的頁面學習LINQ使用? –

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)'並檢查返回值,對於重複項,這將是錯誤的。 –

+0

我認爲這種方式的意圖更清晰 - 即使沒有HashSet 類的知識,其含義應該是顯而易見的。 – sga101

+0

就個人而言,我寧願只知道我使用的API :)(設置附加方法返回它是否實際進行更改是非常常見的 - 它不像這是一個特別「隱藏」的信息位)。您也可以使用ContainsKey然後使用索引器代替TryGetValue作爲字典嗎? –