using Microsoft.Extensions.Configuration; using Phares.Shared; using Serilog; using ShellProgressBar; using View_by_Distance.Delete.By.Distinct.Models; using View_by_Distance.Property.Models; using View_by_Distance.Shared.Models.Methods; namespace View_by_Distance.Delete.By.Distinct; public class DeleteByDistinct { public DeleteByDistinct(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) { if (isSilent) { } if (console is null) { } long ticks = DateTime.Now.Ticks; ILogger? log = Log.ForContext(); Dictionary> longToCollection = new(); Configuration configuration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; configuration.Update(); log.Information(configuration.RootDirectory); bool compareIsPopulatedAndNotTheSame = !string.IsNullOrEmpty(appSettings.CompareRootDirectory) && appSettings.CompareRootDirectory != configuration.RootDirectory; Work(appSettings, ticks, log, configuration.RootDirectory, nameof(configuration.RootDirectory), options, longToCollection, logOnly: compareIsPopulatedAndNotTheSame); if (compareIsPopulatedAndNotTheSame) Work(appSettings, ticks, log, appSettings.CompareRootDirectory, nameof(appSettings.CompareRootDirectory), options, longToCollection, logOnly: false); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(appSettings.CompareRootDirectory); } private static void Work(AppSettings appSettings, long ticks, ILogger log, string directory, string variable, ProgressBarOptions options, Dictionary> longToCollection, bool logOnly) { long check; string message; string logFile; string checkName; int totalSeconds; FileInfo fileInfo; ProgressBar progressBar; List? fileNames; ConsoleKey? consoleKey = null; List deletedFiles = new(); List deletedDirectories = new(); Dictionary> longToCollectionB = new(); List<(string Source, string Destination)> renameFiles = new(); log.Information($"Gathering {appSettings.SearchPattern} files from <{directory}>"); (string directory, string[] files)[] leftCollection = Shared.Models.Stateless.Methods.IFileHolder.GetFiles(directory, appSettings.SearchPattern).ToArray(); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") Looking for duplicates from <{directory}> - {totalSeconds} total second(s)"; progressBar = new(leftCollection.Length, message, options); foreach ((_, string[] files) in leftCollection) { progressBar.Tick(); foreach (string file in files) { if (file.EndsWith(".id") || file.Contains("Rename") || file.EndsWith(".lsv")) continue; fileInfo = new(file); if (appSettings.SizeForLong) { if (fileInfo.Length < 100) continue; check = fileInfo.Length; } else if (appSettings.TicksForLong) { if (fileInfo.LastWriteTime.Hour == 0 && fileInfo.LastWriteTime.Minute == 0 && fileInfo.LastWriteTime.Second == 0) continue; check = fileInfo.LastWriteTime.Ticks; } else throw new Exception(); if (!longToCollection.TryGetValue(check, out fileNames)) { longToCollection.Add(check, new()); if (!longToCollection.TryGetValue(check, out fileNames)) throw new Exception(); } checkName = fileInfo.Name.ToLower().Replace(".jpeg", ".jpg"); if (!logOnly && appSettings.RenameToMatch && fileNames.Count == 1 && fileInfo.DirectoryName is not null && fileInfo.Name != fileNames.First()) renameFiles.Add((fileInfo.FullName, Path.Combine(fileInfo.DirectoryName, fileNames.First()))); else if (fileNames.Contains(checkName)) deletedFiles.Add(file); else fileNames.Add(checkName); } } progressBar.Dispose(); log.Information(". . ."); logFile = $"{ticks}-{variable}-Files-A.lsv"; if (!logOnly) File.WriteAllLines(Path.Combine(directory, logFile), deletedFiles); if (deletedFiles.Any() && !logOnly) { log.Information($"Ready to delete {deletedFiles.Count} from {variable} {appSettings.SearchPattern} file(s)? See <{logFile}>"); for (int y = 0; y < int.MaxValue; y++) { log.Information("Press \"Y\" key to delete file(s), \"N\" key to log file(s) or close console to not delete files"); consoleKey = Console.ReadKey().Key; if (consoleKey is ConsoleKey.Y or ConsoleKey.N) break; } log.Information(". . ."); if (consoleKey is not null && consoleKey.Value == ConsoleKey.Y) { foreach (string file in deletedFiles) { if (!appSettings.RecycleOption) { try { File.Delete(file); } catch (Exception) { } } else { try { Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile(file, Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin); } catch (Exception) { } } } totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") Looking for empty directories from <{directory}> - {totalSeconds} total second(s)"; progressBar = new(4, message, options); for (int i = 1; i < 5; i++) { progressBar.Tick(); List collection = new(); Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(directory, collection); if (!collection.Any()) break; deletedDirectories.AddRange(collection); } progressBar.Dispose(); log.Information(". . ."); logFile = $"{ticks + 1}-{variable}-Directories.lsv"; File.WriteAllLines(Path.Combine(directory, logFile), deletedDirectories.Distinct()); } } if (!logOnly && renameFiles.Any()) { logFile = $"{ticks}-{variable}-Files-B.lsv"; File.WriteAllLines(Path.Combine(directory, logFile), renameFiles.Select(l => l.Source)); logFile = $"{ticks}-{variable}-Files-C.lsv"; File.WriteAllLines(Path.Combine(directory, logFile), renameFiles.Select(l => l.Destination)); log.Information($"Ready to rename to match {renameFiles.Count} from {variable} {appSettings.SearchPattern} file(s)? See <{logFile}>"); for (int y = 0; y < int.MaxValue; y++) { log.Information("Press \"Y\" key to rename to match file(s), \"N\" key to log file(s) or close console to not rename to match files"); consoleKey = Console.ReadKey().Key; if (consoleKey is ConsoleKey.Y or ConsoleKey.N) break; } log.Information(". . ."); if (consoleKey is not null && consoleKey.Value == ConsoleKey.Y) { foreach ((string source, string destination) in renameFiles) { try { File.Move(source, destination); } catch (Exception) { } } } } } }