Compare commits

...

2 Commits

Author SHA1 Message Date
f82beb62ed released 0.4 2025-05-10 21:15:04 +02:00
0bb5fbdf87 implemented analyze command 2025-05-10 21:13:09 +02:00
8 changed files with 128 additions and 3 deletions

BIN
0.4.zip Normal file

Binary file not shown.

View File

@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;Analyze</Configurations>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,108 @@
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 AnalyzeCommand : Command<AnalyzeCommand.Settings>
{
public sealed class Settings : CommandSettings
{
[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<Dictionary<string, Redundancy>>(File.ReadAllText(settings.Path));
var groups = redundancies
.GroupBy(x => Path.GetExtension(x.Value.Paths[0]), x => x.Value)
.ToDictionary(x => x.Key, x => new
{
FileSize = x.Sum(y => y.FileSize),
RedundancySize = x.Sum(y => y.FileSize) * (x.Sum(y => y.Paths.Count) - 1),
RedundancyCount = x.Sum(y => y.Paths.Count)-1,
});
// x => new { FileSize = x, RedundancySize = x.Sum()*(x.Count()-1)}
var extensions = settings.Extensions.Split(",", StringSplitOptions.RemoveEmptyEntries);
var table = new Table();
table.AddColumn("Type");
table.AddColumn(new TableColumn("Size").RightAligned());
table.AddColumn(new TableColumn("Redundancy size").RightAligned());
table.AddColumn(new TableColumn("Redundancy count").RightAligned());
foreach (var extension in extensions)
{
if (groups.ContainsKey(extension))
{
var size = groups[extension].FileSize;
var sizeFormat = GetSizeFormat((ulong)size);
var redundancySize = groups[extension].RedundancySize;
var redundancySizeFormat = GetSizeFormat((ulong)redundancySize);
table.AddRow(
new Text(extension),
new Markup($"[green]{sizeFormat}[/]"),
new Markup($"[yellow]{redundancySizeFormat}[/]"),
new Markup($"{groups[extension].RedundancyCount}"));
}
}
AnsiConsole.Write(table);
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;
}
}
}

View File

@ -50,6 +50,15 @@ namespace RedundancyFinderCLI
SaveRedundancies(finder, settings.OutputPath);
};
// Register the CancelKeyPress event to handle Ctrl+C
Console.CancelKeyPress += (sender, e) =>
{
e.Cancel = true; // Prevent the process from terminating immediately
WriteLine("[yellow]Ctrl+C detected. Saving redundancies before exiting...[/]");
SaveRedundancies(finder, settings.OutputPath ?? "redundancies.json");
Environment.Exit(0); // Exit the application gracefully
};
// Load existing redundancies if the output file exists
if (File.Exists(settings.OutputPath))
{

View File

@ -12,7 +12,9 @@ internal class Program
var app = new CommandApp<FinderCommand>();
app.Configure(config =>
{
config.AddCommand<AnalyzeCommand>("analyze");
#if DEBUG
config.PropagateExceptions();
config.ValidateExamples();
#endif

View File

@ -3,6 +3,10 @@
"RedundancyFinderCLI": {
"commandName": "Project",
"commandLineArgs": "C:\\Users\\daskn\\Pictures\\ -v"
},
"Analyze": {
"commandName": "Project",
"commandLineArgs": "analyze"
}
}
}

View File

@ -5,6 +5,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;Analyze</Configurations>
</PropertyGroup>
<ItemGroup>

View File

@ -1,11 +1,11 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35818.85 d17.13
VisualStudioVersion = 17.13.35818.85
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedundancyFinder", "RedundancyFinder\RedundancyFinder.csproj", "{925C533F-2205-4848-B742-CB013F81DF91}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RedundancyFinder", "RedundancyFinder\RedundancyFinder.csproj", "{925C533F-2205-4848-B742-CB013F81DF91}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedundancyFinderCLI", "RedundancyFinderCLI\RedundancyFinderCLI.csproj", "{7187EE24-4F0D-48F3-B76C-DAECD4A96F76}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RedundancyFinderCLI", "RedundancyFinderCLI\RedundancyFinderCLI.csproj", "{7187EE24-4F0D-48F3-B76C-DAECD4A96F76}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution