public async Task<QuerySummary> QueryAsync(string sourcePath, bool recursive, QueryType queries, params MetaType[] types) { if (String.IsNullOrEmpty(sourcePath)) throw new ArgumentNullException(nameof(sourcePath)); if (!Directory.Exists(sourcePath)) throw new DirectoryNotFoundException(sourcePath); if (queries == QueryType.None) throw new ArgumentException("No queries given."); Dictionary<string, IEnumerable<Tuple<string, QueryType>>> duplicates = new Dictionary<string, IEnumerable<Tuple<string, QueryType>>>(); Dictionary<string, string> md5sums = new Dictionary<string, string>(); Dictionary<string, string> sha1sums = new Dictionary<string, string>(); IEnumerable<MetaData> data = await GetMetaData(sourcePath, recursive, types); foreach (MetaData item in data.Where(x => x.Type != MetaType.Directory && x.Type != MetaType.File)) { List<Tuple<string, QueryType>> matches = new List<Tuple<string, QueryType>>(); foreach (MetaData other in data.Where(x => x.Type != MetaType.Directory && x.Type != MetaType.File && !x.Equals(item))) { QueryType match = QueryType.None; bool equalFilename = Path.GetFileName(item.Path).Equals(Path.GetFileName(other.Path), StringComparison.Ordinal /* TODO: which type? */); if (queries.HasFlag(QueryType.EqualFileName) && equalFilename) match |= QueryType.EqualFileName; if (queries.HasFlag(QueryType.EqualFileNameDifferentFileSize) && equalFilename) { if (item.Data[MetaKey.Size] != other.Data[MetaKey.Size]) match |= QueryType.EqualFileNameDifferentFileSize; } if (queries.HasFlag(QueryType.EqualChecksumMD5) || queries.HasFlag(QueryType.EqualFileNameDifferentChecksumMD5)) { string md5item; if (!md5sums.TryGetValue(item.Path, out md5item)) { md5item = GetMD5(item.Path); md5sums[item.Path] = md5item; } string md5other; if (!md5sums.TryGetValue(other.Path, out md5other)) { md5other = GetMD5(other.Path); md5sums[other.Path] = md5other; } bool md5match = md5item.Equals(md5other, StringComparison.Ordinal); if (queries.HasFlag(QueryType.EqualChecksumMD5) && md5match) match |= QueryType.EqualChecksumMD5; if (queries.HasFlag(QueryType.EqualFileNameDifferentChecksumMD5) && equalFilename && !md5match) match |= QueryType.EqualFileNameDifferentChecksumMD5; } if (queries.HasFlag(QueryType.EqualChecksumSHA1) || queries.HasFlag(QueryType.EqualFileNameDifferentChecksumSHA1)) { string sha1item; if (!sha1sums.TryGetValue(item.Path, out sha1item)) { sha1item = GetSHA1(item.Path); sha1sums[item.Path] = sha1item; } string sha1other; if (!sha1sums.TryGetValue(other.Path, out sha1other)) { sha1other = GetSHA1(other.Path); sha1sums[other.Path] = sha1other; } bool sha1match = sha1item.Equals(sha1other, StringComparison.Ordinal); if (queries.HasFlag(QueryType.EqualChecksumSHA1) && sha1match) match |= QueryType.EqualChecksumSHA1; if (queries.HasFlag(QueryType.EqualFileNameDifferentChecksumSHA1) && equalFilename && !sha1match) match |= QueryType.EqualFileNameDifferentChecksumSHA1; } if ((queries.HasFlag(QueryType.LowResolution) || queries.HasFlag(QueryType.EqualFileNameDifferentResolution)) && item.Data.ContainsKey(MetaKey.Resolution)) { //const int limit = 960 * 1280; const int resolutionLimit = 1024 * 768; int resolutionItem = (int)item.Data[MetaKey.Width] * (int)item.Data[MetaKey.Height]; if (resolutionItem <= resolutionLimit) match |= QueryType.LowResolution; if (queries.HasFlag(QueryType.EqualFileNameDifferentResolution) && other.Data.ContainsKey(MetaKey.Resolution) && equalFilename) { int resolutionOther = (int)other.Data[MetaKey.Width] * (int)other.Data[MetaKey.Height]; if (resolutionItem != resolutionOther) match |= QueryType.EqualFileNameDifferentResolution; } } if (match != QueryType.None) matches.Add(Tuple.Create(other.Path, match)); } if (matches.Count > 0) duplicates[item.Path] = matches; } QuerySummary result = new QuerySummary(); result.duplicates = duplicates; return result; }
public async Task <QuerySummary> QueryAsync(string sourcePath, bool recursive, QueryType queries, params MetaType[] types) { if (String.IsNullOrEmpty(sourcePath)) { throw new ArgumentNullException(nameof(sourcePath)); } if (!Directory.Exists(sourcePath)) { throw new DirectoryNotFoundException(sourcePath); } if (queries == QueryType.None) { throw new ArgumentException("No queries given."); } Dictionary <string, IEnumerable <Tuple <string, QueryType> > > allMatches = new Dictionary <string, IEnumerable <Tuple <string, QueryType> > >(); Dictionary <string, string> md5sums = new Dictionary <string, string>(); Dictionary <string, string> sha1sums = new Dictionary <string, string>(); Dictionary <string, string> sha256sums = new Dictionary <string, string>(); IEnumerable <MetaData> data = await GetMetaData(sourcePath, recursive, types); foreach (MetaData item in data.Where(x => x.Type != MetaType.Directory && x.Type != MetaType.File)) { List <Tuple <string, QueryType> > matches = new List <Tuple <string, QueryType> >(); foreach (MetaData other in data.Where(x => x.Type != MetaType.Directory && x.Type != MetaType.File && !x.Equals(item))) { QueryType match = QueryType.None; bool equalFilename = Path.GetFileName(item.Path).Equals(Path.GetFileName(other.Path), StringComparison.Ordinal); if (queries.HasFlag(QueryType.EqualFileName) && equalFilename) { match |= QueryType.EqualFileName; } if (queries.HasFlag(QueryType.EqualFileNameDifferentFileSize) && equalFilename) { if (RequireMetaKey(MetaKey.Size, item, other)) { if (item.Data[MetaKey.Size] != other.Data[MetaKey.Size]) { match |= QueryType.EqualFileNameDifferentFileSize; } } } if (queries.HasFlag(QueryType.EqualChecksumMD5) || queries.HasFlag(QueryType.EqualFileNameDifferentChecksumMD5)) { string md5item; if (!md5sums.TryGetValue(item.Path, out md5item)) { using (FileStream fileStream = File.OpenRead(item.Path)) md5item = fileStream.GetMD5Sum(); md5sums[item.Path] = md5item; } string md5other; if (!md5sums.TryGetValue(other.Path, out md5other)) { using (FileStream fileStream = File.OpenRead(other.Path)) md5other = fileStream.GetMD5Sum(); md5sums[other.Path] = md5other; } bool md5match = md5item.Equals(md5other, StringComparison.Ordinal); if (queries.HasFlag(QueryType.EqualChecksumMD5) && md5match) { match |= QueryType.EqualChecksumMD5; } if (queries.HasFlag(QueryType.EqualFileNameDifferentChecksumMD5) && equalFilename && !md5match) { match |= QueryType.EqualFileNameDifferentChecksumMD5; } } if (queries.HasFlag(QueryType.EqualChecksumSHA1) || queries.HasFlag(QueryType.EqualFileNameDifferentChecksumSHA1)) { string sha1item; if (!sha1sums.TryGetValue(item.Path, out sha1item)) { using (FileStream fileStream = File.OpenRead(item.Path)) sha1item = fileStream.GetSHA1Sum(); sha1sums[item.Path] = sha1item; } string sha1other; if (!sha1sums.TryGetValue(other.Path, out sha1other)) { using (FileStream fileStream = File.OpenRead(other.Path)) sha1other = fileStream.GetSHA1Sum(); sha1sums[other.Path] = sha1other; } bool sha1match = sha1item.Equals(sha1other, StringComparison.Ordinal); if (queries.HasFlag(QueryType.EqualChecksumSHA1) && sha1match) { match |= QueryType.EqualChecksumSHA1; } if (queries.HasFlag(QueryType.EqualFileNameDifferentChecksumSHA1) && equalFilename && !sha1match) { match |= QueryType.EqualFileNameDifferentChecksumSHA1; } } if (queries.HasFlag(QueryType.EqualChecksumSHA256) || queries.HasFlag(QueryType.EqualFileNameDifferentChecksumSHA256)) { string sha256item; if (!sha256sums.TryGetValue(item.Path, out sha256item)) { using (FileStream fileStream = File.OpenRead(item.Path)) sha256item = fileStream.GetSHA256Sum(); sha256sums[item.Path] = sha256item; } string sha256other; if (!sha256sums.TryGetValue(other.Path, out sha256other)) { using (FileStream fileStream = File.OpenRead(other.Path)) sha256other = fileStream.GetSHA256Sum(); sha256sums[other.Path] = sha256other; } bool sha256match = sha256item.Equals(sha256other, StringComparison.Ordinal); if (queries.HasFlag(QueryType.EqualChecksumSHA256) && sha256match) { match |= QueryType.EqualChecksumSHA256; } if (queries.HasFlag(QueryType.EqualFileNameDifferentChecksumSHA256) && equalFilename && !sha256match) { match |= QueryType.EqualFileNameDifferentChecksumSHA256; } } if (queries.HasFlag(QueryType.LowResolution) || queries.HasFlag(QueryType.EqualFileNameDifferentResolution)) { if (RequireMetaKey(MetaKey.Width, item) && RequireMetaKey(MetaKey.Height, item)) { //const int limit = 960 * 1280; const int resolutionLimit = 1024 * 768; int resolutionItem = (int)item.Data[MetaKey.Width] * (int)item.Data[MetaKey.Height]; if (queries.HasFlag(QueryType.LowResolution) && resolutionItem <= resolutionLimit) { match |= QueryType.LowResolution; } if (queries.HasFlag(QueryType.EqualFileNameDifferentResolution) && equalFilename) { if (RequireMetaKey(MetaKey.Width, other) && RequireMetaKey(MetaKey.Height, other)) { int resolutionOther = (int)other.Data[MetaKey.Width] * (int)other.Data[MetaKey.Height]; if (resolutionItem != resolutionOther) { match |= QueryType.EqualFileNameDifferentResolution; } } } } } if (match != QueryType.None) { matches.Add(Tuple.Create(other.Path, match)); } } if (matches.Count > 0) { allMatches[item.Path] = CleanupMatches(matches); } } QuerySummary result = new QuerySummary(); result.matches = allMatches; return(result); }