我知道这是一个 PowerShell 问题,但您可以在 C# 中充分利用并行化。您还在其中一个 cmets 中提到了使用 C# 作为替代方案,所以我认为发布可能的实现方式不会有什么坏处。
您可以先创建一个方法来计算文件的 MD5 校验和:
private static string CalculateMD5(string filename)
{
using var md5 = MD5.Create();
using var stream = File.OpenRead(filename);
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
}
然后您可以使用ParallelEnumerable.AsParallel() 查询所有文件哈希的并行方法:
private static IEnumerable<FileHash> FindFileHashes(string directoryPath)
{
var allFiles = Directory
.EnumerateFiles(directoryPath, "*", SearchOption.AllDirectories);
var hashedFiles = allFiles
.AsParallel()
.Select(filename => new FileHash {
FileName = filename,
Hash = CalculateMD5(filename)
});
return hashedFiles;
}
那么就可以简单的使用上面的方法删除重复文件了:
private static void DeleteDuplicateFiles(string directoryPath)
{
var fileHashes = new HashSet<string>();
foreach (var fileHash in FindFileHashes(directoryPath))
{
if (!fileHashes.Contains(fileHash.Hash))
{
Console.WriteLine($"Found - File : {fileHash.FileName} Hash : {fileHash.Hash}");
fileHashes.Add(fileHash.Hash);
continue;
}
Console.WriteLine($"Deleting - File : {fileHash.FileName} Hash : {fileHash.Hash}");
File.Delete(fileHash.FileName);
}
}
完整计划:
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Security.Cryptography;
namespace Test
{
internal class FileHash
{
public string FileName { get; set; }
public string Hash { get; set; }
}
public class Program
{
public static void Main()
{
var path = "C:\\Path\To\Files";
if (File.Exists(path))
{
Console.WriteLine($"Deleting duplicate files at {path}");
DeleteDuplicateFiles(path);
}
}
private static void DeleteDuplicateFiles(string directoryPath)
{
var fileHashes = new HashSet<string>();
foreach (var fileHash in FindFileHashes(directoryPath))
{
if (!fileHashes.Contains(fileHash.Hash))
{
Console.WriteLine($"Found - File : {fileHash.FileName} Hash : {fileHash.Hash}");
fileHashes.Add(fileHash.Hash);
continue;
}
Console.WriteLine($"Deleting - File : {fileHash.FileName} Hash : {fileHash.Hash}");
File.Delete(fileHash.FileName);
}
}
private static IEnumerable<FileHash> FindFileHashes(string directoryPath)
{
var allFiles = Directory
.EnumerateFiles(directoryPath, "*", SearchOption.AllDirectories);
var hashedFiles = allFiles
.AsParallel()
.Select(filename => new FileHash {
FileName = filename,
Hash = CalculateMD5(filename)
});
return hashedFiles;
}
private static string CalculateMD5(string filename)
{
using var md5 = MD5.Create();
using var stream = File.OpenRead(filename);
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
}
}
}