diff --git a/RedundancyFinderCLI/AnalyzeCommand.cs b/RedundancyFinderCLI/AnalyzeCommand.cs index 121d09c..8d0ae9b 100644 --- a/RedundancyFinderCLI/AnalyzeCommand.cs +++ b/RedundancyFinderCLI/AnalyzeCommand.cs @@ -24,7 +24,7 @@ namespace RedundancyFinderCLI [Description("File extensions to search for. Comma separated.")] [CommandOption("-e|--extensions")] - [DefaultValue(".jpg,.webp,.raw,.pdf,.xsl,.xslx,.doc,.docx,.txt,.jpeg,.mov,.mp4,.mp3,.wav,.bmp,.gif,.png,.cu,.mid,.msb ,.mov,.avi,.wmv,.flv,.m4v,.bak ,.cpr ,.xml,.psd")] + [DefaultValue(".jpg,.webp,.raw,.pdf,.xsl,.xslx,.doc,.docx,.txt,.jpeg,.mov,.mp4,.mp3,.wav,.bmp,.gif,.png,.cu,.mid,.msb,.mov,.avi,.wmv,.flv,.m4v,.bak ,.cpr,.xml,.psd")] public string? Extensions { get; init; } [Description("Show all information.")] diff --git a/RedundancyFinderCLI/DeleteCommand.cs b/RedundancyFinderCLI/DeleteCommand.cs new file mode 100644 index 0000000..d587453 --- /dev/null +++ b/RedundancyFinderCLI/DeleteCommand.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using Newtonsoft.Json; +using RedundancyFinder; +using Spectre.Console; +using Spectre.Console.Cli; +namespace RedundancyFinderCLI +{ + internal sealed class DeleteCommand : Command + { + public sealed class Settings : CommandSettings + { + [Description("Paths to Keep.")] + [DefaultValue(new string[] { "H:\\" })] + [CommandArgument(1, "[path]")] + public string[]? FoldersToKeep { get; init; } + + [Description("Path to analyze.")] + [DefaultValue("redundancies.json")] + [CommandArgument(0, "[path]")] + public string? Path { get; init; } + + [Description("File extensions to search for. Comma separated.")] + [CommandOption("-e|--extensions")] + [DefaultValue(".jpg,.webp,.raw,.pdf,.xsl,.xslx,.doc,.docx,.txt,.jpeg,.mov,.mp4,.mp3,.wav,.bmp,.gif,.png,.cu,.mid,.msb,.mov,.avi,.wmv,.flv,.m4v,.bak,.cpr,.xml,.psd")] + public string? Extensions { get; init; } + + [Description("Show all information.")] + [CommandOption("-v|--verbose")] + [DefaultValue(false)] + public bool Verbose { get; init; } + + } + public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings) + { + WriteLine($"[yellow]Analyzing {settings.Path}[/]"); + + var redundancies = JsonConvert.DeserializeObject>(File.ReadAllText(settings.Path)); + + var pathsToDelete = new List(); + + foreach (var redundancy in redundancies.Values) + { + var pathToKeep = redundancy.Paths.FirstOrDefault(x => settings.FoldersToKeep.Any(y => x.StartsWith(y))); + if (pathToKeep != default) + { + + foreach (var path in redundancy.Paths) + { + if (path != pathToKeep) + { + pathsToDelete.Add(path); + } + } + } + else if(settings.Verbose) + { + if (redundancy.Paths.Count > 0) + { + WriteLine($"[blue]Skipping [/]'{redundancy.Paths.FirstOrDefault()}'[blue]. No paths to keep![/]"); + } + else + { + WriteLine($"[yellow]Skipping [/]'{redundancy.Hash}'[/].[blue] No paths![/]"); + } + + } + } + + + foreach (var path in pathsToDelete) + { + AnsiConsole.WriteLine(path); + } + if (pathsToDelete.Count == 0) + { + WriteLine("[yellow]Nothing to delete![/]"); + + return 0; + } + var confirmation = AnsiConsole.Prompt( + new TextPrompt("Delete all of the above?") + .AddChoice(true) + .AddChoice(false) + .DefaultValue(true) + .WithConverter(choice => choice ? "y" : "n")); + + if (confirmation) + { + foreach (var path in pathsToDelete) + { + try + { + File.Delete(path); + } + catch (Exception e) + { + WriteLine($"[red]Error deleting file: [/]'{path}'\nMessage:\n{e.Message}"); + } + + WriteLine($"[yellow]Deleted file: [/]'{path}'"); + } + } + return 0; + } + + + private void WriteLine(string v) + { + string now = Markup.Escape($"[{DateTime.Now.ToString("HH:mm:ss")}]"); + AnsiConsole.MarkupLine($"[gray]{now}[/] {v}"); + } + + private static string GetSizeFormat(ulong totalSize) + { + string sizeUnit = "B"; + double size = totalSize; + while (size > 1024) + { + size /= 1024d; + sizeUnit = sizeUnit switch + { + "B" => "KB", + "KB" => "MB", + "MB" => "GB", + "GB" => "TB", + _ => sizeUnit + }; + + } + string sizeFormat = $"{size:.00} {sizeUnit}"; + return sizeFormat; + } + } +} diff --git a/RedundancyFinderCLI/Program.cs b/RedundancyFinderCLI/Program.cs index d2d9c0a..feb5640 100644 --- a/RedundancyFinderCLI/Program.cs +++ b/RedundancyFinderCLI/Program.cs @@ -13,6 +13,7 @@ internal class Program app.Configure(config => { config.AddCommand("analyze"); + config.AddCommand("delete"); #if DEBUG config.PropagateExceptions(); diff --git a/RedundancyFinderCLI/Properties/launchSettings.json b/RedundancyFinderCLI/Properties/launchSettings.json index cc974c5..51ea2fa 100644 --- a/RedundancyFinderCLI/Properties/launchSettings.json +++ b/RedundancyFinderCLI/Properties/launchSettings.json @@ -7,6 +7,10 @@ "Analyze": { "commandName": "Project", "commandLineArgs": "analyze" + }, + "Delete": { + "commandName": "Project", + "commandLineArgs": "delete -v" } } } \ No newline at end of file