Major additons
Converted to new project structure Check if db already exists Add vacuum for db cleanup Check if filehash already exits and write info to console
This commit is contained in:
25
src/Chksum.Tests/Chksum.Tests.csproj
Normal file
25
src/Chksum.Tests/Chksum.Tests.csproj
Normal file
@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
2
src/Chksum.Tests/Usings.cs
Normal file
2
src/Chksum.Tests/Usings.cs
Normal file
@ -0,0 +1,2 @@
|
||||
global using Xunit;
|
||||
global using FluentAssertions;
|
8
src/Chksum.Tests/doTheThingTest.cs
Normal file
8
src/Chksum.Tests/doTheThingTest.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Chksum.Tests;
|
||||
|
||||
public class doTheThingTest {
|
||||
[Fact]
|
||||
public void doTheThing_willNotThrowAnException() {
|
||||
|
||||
}
|
||||
}
|
22
src/Chksum/Chksum.csproj
Normal file
22
src/Chksum/Chksum.csproj
Normal file
@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Chksum.Tests\Chksum.Tests.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<SelfContained>true</SelfContained>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.8" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
87
src/Chksum/Program.cs
Normal file
87
src/Chksum/Program.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using Chksum.Utils;
|
||||
|
||||
public class Program {
|
||||
static void Main(string[] args) {
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
if (args.Length == 0) {
|
||||
Console.WriteLine("Please specify an option.");
|
||||
PrintAvailableOptions();
|
||||
return;
|
||||
} else if (args.Length > 1) {
|
||||
Console.WriteLine("Too many options.");
|
||||
return;
|
||||
}
|
||||
|
||||
ChksumUtils utils = new ChksumUtils();
|
||||
|
||||
utils.getBaseDir();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
switch (args[0]) {
|
||||
case "checksum":
|
||||
Console.WriteLine("Starting the checksum process.");
|
||||
Console.ResetColor();
|
||||
|
||||
utils.doTheThing();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("Checksum process finished");
|
||||
break;
|
||||
case "countmd5":
|
||||
Console.WriteLine("Counting md5 checksum files.");
|
||||
Console.ResetColor();
|
||||
|
||||
utils.countAllMd5Checksums();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("Finished counting all md5 checksum files.");
|
||||
break;
|
||||
case "deletemd5":
|
||||
Console.WriteLine("Deleting all md5 checksum files.");
|
||||
Console.ResetColor();
|
||||
|
||||
utils.deleteAllMd5Checksums();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("Deleted all md5 checksum files.");
|
||||
break;
|
||||
case "compareChecksums":
|
||||
Console.WriteLine("Comparing all md5 checksum files. If there is none, creating one.");
|
||||
Console.ResetColor();
|
||||
|
||||
utils.compareChecksums();
|
||||
break;
|
||||
case "createDB":
|
||||
utils.initializeDB();
|
||||
break;
|
||||
case "help":
|
||||
PrintAvailableOptions();
|
||||
break;
|
||||
default:
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("Invalid option. Maybe you mistyped it?");
|
||||
PrintAvailableOptions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintAvailableOptions() {
|
||||
String[] options = {
|
||||
"checksum",
|
||||
"countmd5",
|
||||
"deletemd5",
|
||||
"compareChecksums",
|
||||
"createDB",
|
||||
"help"
|
||||
};
|
||||
|
||||
Console.ResetColor();
|
||||
Console.WriteLine("usage: chksum [option]");
|
||||
Console.WriteLine("Here is a list of all available options:");
|
||||
foreach (String option in options) {
|
||||
Console.WriteLine("\t" + option);
|
||||
}
|
||||
}
|
||||
}
|
198
src/Chksum/chksum.cs
Normal file
198
src/Chksum/chksum.cs
Normal file
@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
// Go into folder
|
||||
// Check if any file is in there
|
||||
// If there is a file. Calculate md5sum > filename.md5
|
||||
// If there is no file. Repeat
|
||||
|
||||
namespace Chksum.Utils;
|
||||
public class ChksumUtils {
|
||||
|
||||
// int getDirectoryCount() {
|
||||
// int folderCount = Directory.GetDirectories(Directory.GetCurrentDirectory()).Length; // Get folder count in current directory
|
||||
// return folderCount;
|
||||
// }
|
||||
|
||||
private int getFileCount() {
|
||||
int fileCount = Directory.GetFiles(Directory.GetCurrentDirectory()).Length; // Get file count in current directory
|
||||
return fileCount;
|
||||
}
|
||||
|
||||
// string getParentFolder() {
|
||||
// string parentFolder = Directory.GetParent(Directory.GetCurrentDirectory()).ToString(); // Get parent folder of current directory
|
||||
// return parentFolder;
|
||||
// }
|
||||
|
||||
public string DatabaseRoot { get; set; }
|
||||
public void getBaseDir() {
|
||||
DatabaseRoot = AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
|
||||
public void initializeDB() {
|
||||
if (!File.Exists("chksum.db")) {
|
||||
using (var connection = new SqliteConnection("Data Source=chksum.db")) {
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
CREATE TABLE file (
|
||||
filehash TEXT NOT NULL PRIMARY KEY,
|
||||
filename TEXT NOT NULL,
|
||||
pathtofile TEXT NOT NULL,
|
||||
artist TEXT,
|
||||
playbacklength INTEGER
|
||||
);
|
||||
";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanDB() {
|
||||
using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db")) {
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
vacuum;
|
||||
";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
private string CalculateMD5(string filename) {
|
||||
using (var md5 = System.Security.Cryptography.MD5.Create()) {
|
||||
using (var stream = File.OpenRead(filename)) {
|
||||
var hash = md5.ComputeHash(stream);
|
||||
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doTheThing() {
|
||||
foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db;Mode=ReadWrite")) {
|
||||
Directory.SetCurrentDirectory(directory); // Set new root
|
||||
if (getFileCount() >= 1) {
|
||||
DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory());
|
||||
FileInfo[] files = dir.GetFiles();
|
||||
foreach (FileInfo file in files) {
|
||||
string fileName = file.Name;
|
||||
string absolutePathToFile = Path.GetFullPath(fileName);
|
||||
string pathToFile = Path.GetRelativePath(DatabaseRoot, absolutePathToFile);
|
||||
string fileHash = CalculateMD5(fileName);
|
||||
|
||||
if (checkIfFileAlreadyExists(fileHash, fileName) == false) {
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
INSERT INTO file (filehash, filename, pathtofile)
|
||||
VALUES ($filehash, $filename, $pathtofile)
|
||||
";
|
||||
command.Parameters.AddWithValue("$filehash", fileHash);
|
||||
command.Parameters.AddWithValue("$filename", fileName);
|
||||
command.Parameters.AddWithValue("$pathtofile", pathToFile);
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
doTheThing();
|
||||
}
|
||||
}
|
||||
|
||||
private bool checkIfFileAlreadyExists(string fileHash, string fileName) {
|
||||
string filehash = string.Empty;
|
||||
string filename = string.Empty;
|
||||
|
||||
using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db;Mode=ReadWrite")) {
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
SELECT filehash, filename FROM file WHERE filehash = $filehash
|
||||
";
|
||||
command.Parameters.AddWithValue("$filehash", fileHash);
|
||||
|
||||
using (var reader = command.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
filehash = reader.GetString(0);
|
||||
filename = reader.GetString(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileHash == filehash) {
|
||||
Console.WriteLine($"Duplicate files found: {fileName} with the hash {fileHash} is identical to {filename} with the hash {filehash}");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int getTotalFileCount() {
|
||||
int totalFileCount = Directory.GetFiles(Directory.GetCurrentDirectory(), "*", SearchOption.AllDirectories).Length;
|
||||
return totalFileCount - 1; // Remove the program from the totalFileCount
|
||||
}
|
||||
|
||||
public void countAllMd5Checksums() {
|
||||
int totalMD5FileCount = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.md5", SearchOption.AllDirectories).Length;
|
||||
Console.WriteLine("There are " + totalMD5FileCount + " md5 checksums");
|
||||
}
|
||||
|
||||
public void deleteAllMd5Checksums() {
|
||||
foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) {
|
||||
Directory.SetCurrentDirectory(directory); // Set new root
|
||||
if (getFileCount() >= 1) {
|
||||
DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory());
|
||||
FileInfo[] files = dir.GetFiles();
|
||||
foreach (FileInfo file in files) {
|
||||
string fileName = file.Name;
|
||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
|
||||
string checksumFile = Directory.GetCurrentDirectory() + "/" + fileNameWithoutExtension + ".md5";
|
||||
File.Delete(checksumFile);
|
||||
Console.WriteLine("Deleted " + checksumFile);
|
||||
}
|
||||
}
|
||||
deleteAllMd5Checksums();
|
||||
}
|
||||
}
|
||||
|
||||
public void compareChecksums() {
|
||||
foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) {
|
||||
Directory.SetCurrentDirectory(directory); // Set new root
|
||||
if (getFileCount() >= 1) {
|
||||
DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory());
|
||||
FileInfo[] files = dir.GetFiles();
|
||||
// files.ToList().ForEach(i => Console.WriteLine(i.ToString())); // Print all files in files array
|
||||
foreach (FileInfo file in files) {
|
||||
string fileName = file.Name;
|
||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
|
||||
string checksumFile = Directory.GetCurrentDirectory() + "/" + fileNameWithoutExtension + ".md5";
|
||||
string fileMd5Checksum = fileNameWithoutExtension + ".md5";
|
||||
if (File.Exists(fileMd5Checksum)) {
|
||||
string newFileChecksum = CalculateMD5(fileName) + " " + fileName;
|
||||
string existingFileChecksum = File.ReadAllText(fileMd5Checksum);
|
||||
string newFileName = newFileChecksum.Substring(34);
|
||||
string existingFileName = existingFileChecksum.Substring(34);
|
||||
if (newFileChecksum.Equals(existingFileChecksum)) {
|
||||
Console.WriteLine(newFileName + " and " + existingFileName + " are the same.");
|
||||
} else {
|
||||
Console.WriteLine(newFileName + " and " + existingFileName + " are not the same.");
|
||||
Console.WriteLine("The checksum of " + newFileName + " is " + newFileChecksum);
|
||||
Console.WriteLine("The checksum of the already exting file " + existingFileName + " is " + existingFileChecksum);
|
||||
// TODO Tell the user to check which file is the correct one
|
||||
}
|
||||
} else {
|
||||
File.AppendAllText(checksumFile, CalculateMD5(fileName) + " " + fileName);
|
||||
Console.WriteLine("Calculated checksum for: " + checksumFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
compareChecksums();
|
||||
}
|
||||
}
|
||||
}
|
0
src/Chksum/debugchksum.cs
Normal file
0
src/Chksum/debugchksum.cs
Normal file
28
src/chksum.sln
Normal file
28
src/chksum.sln
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chksum", "Chksum\Chksum.csproj", "{BBC56294-03CF-42E0-A838-75AF41EEE32B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chksum.Tests", "Chksum.Tests\Chksum.Tests.csproj", "{239727BC-7124-4985-A6F3-2700295AA06F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BBC56294-03CF-42E0-A838-75AF41EEE32B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BBC56294-03CF-42E0-A838-75AF41EEE32B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BBC56294-03CF-42E0-A838-75AF41EEE32B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BBC56294-03CF-42E0-A838-75AF41EEE32B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{239727BC-7124-4985-A6F3-2700295AA06F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{239727BC-7124-4985-A6F3-2700295AA06F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{239727BC-7124-4985-A6F3-2700295AA06F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{239727BC-7124-4985-A6F3-2700295AA06F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Reference in New Issue
Block a user