private async Task ScanAsync(CancellationToken cancellationToken) { _logger.LogInformation("Loading cache, creating file system structure ..."); using var listOfCaches = new DisposableList(); foreach (var target in _configuration.TargetDirs) { var cacheContext = await GetCacheDirectoryAsync(target, cancellationToken); listOfCaches.Add(cacheContext); if (cancellationToken.IsCancellationRequested) { break; } } if (cancellationToken.IsCancellationRequested) { await SaveCacheAsync(listOfCaches); } cancellationToken.ThrowIfCancellationRequested(); _logger.LogInformation("Searching duplicates ..."); var duplicates = FindDuplicates(listOfCaches.SelectMany(x => x.Cache.Data)).ToList(); if (duplicates.Any()) { _logger.LogInformation($"Duplicates found ({duplicates.Count()})"); if (File.Exists(_configuration.DuplicatesPath)) { _logger.LogInformation( $"Duplicates file report `{_configuration.DuplicatesPath}` found and will be deleted."); File.Delete(_configuration.DuplicatesPath); } await using var duplicatesFile = new FileStream(_configuration.DuplicatesPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, 1024, true); await using var sw = new StreamWriter(duplicatesFile, Encoding.UTF8); foreach (var dup in duplicates) { await sw.WriteLineAsync("---"); foreach (var d in dup) { await sw.WriteLineAsync(d.Path); } } await duplicatesFile.FlushAsync(cancellationToken); _logger.LogInformation( $"Duplicates file report `{_configuration.DuplicatesPath}` saved."); if (_configuration.DuplicateDelete && (_configuration.DeletingMasks?.Any() ?? false)) { foreach (var mask in _configuration.DeletingMasks) { _logger.LogInformation("Deleting duplicates by mask `{0}`", mask); foreach (var group in duplicates) { var g = group.Where(x => _fileNameMaskMatcher.IsMatch(x.Path, mask)).Select(x => x.Path); if (g.Count() < group.Count()) { foreach (var fileForDelete in g) { _logger.LogInformation("Deleting: `{0}`", fileForDelete); File.Delete(fileForDelete); } } else { if (_configuration.KeepSingleFileInDirectoryIfMultiple) { var keepFirst = g.First(); foreach (var fileForDelete in g) { if (fileForDelete == keepFirst) { continue; } _logger.LogInformation("Deleting: `{0}`", fileForDelete); File.Delete(fileForDelete); } } } } } } } else { _logger.LogInformation("There are no duplicates. Deleting: `{0}`", _configuration.DuplicatesPath); File.Delete(_configuration.DuplicatesPath); } await SaveCacheAsync(listOfCaches); }