diff --git a/Metadata/Models/Stateless/Methods/IMetadata.cs b/Metadata/Models/Stateless/Methods/IMetadata.cs index 0fd4c02..80ab5f5 100644 --- a/Metadata/Models/Stateless/Methods/IMetadata.cs +++ b/Metadata/Models/Stateless/Methods/IMetadata.cs @@ -3,15 +3,10 @@ namespace View_by_Distance.Metadata.Models.Stateless.Methods; public interface IMetadata { - DateTime? TestStatic_GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories) => - GetMinimumDateTime(dateTimes, year, directories); - static DateTime? GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList directories) => - Metadata.GetMinimumDateTime(directories, dateTimes, year); - DateTime? TestStatic_GetMinimumDateTime(IReadOnlyList directories) => GetMinimumDateTime(directories); static DateTime? GetMinimumDateTime(IReadOnlyList directories) => - Metadata.GetMinimumDateTime(directories, dateTimes: null, year: null); + Metadata.GetMinimumDateTime(directories); string? TestStatic_GetModel(IReadOnlyList directories) => GetModel(directories); diff --git a/Metadata/Models/Stateless/Methods/Metadata.cs b/Metadata/Models/Stateless/Methods/Metadata.cs index 8894774..ac24dbe 100644 --- a/Metadata/Models/Stateless/Methods/Metadata.cs +++ b/Metadata/Models/Stateless/Methods/Metadata.cs @@ -53,11 +53,11 @@ internal class Metadata return result; } - internal static DateTime? GetMinimumDateTime(IReadOnlyList directories, DateTime?[]? dateTimes, int? year) + internal static DateTime? GetMinimumDateTime(IReadOnlyList directories) { DateTime? result; DateTime dateTime; - List results = dateTimes is null ? new() : (from l in dateTimes where l is not null select l.Value).ToList(); + List results = new(); ExifDirectoryBase? exifDirectoryBase = directories.OfType().FirstOrDefault(); if (exifDirectoryBase is not null) { @@ -86,10 +86,7 @@ internal class Metadata if (quickTimeTrackHeaderDirectory.TryGetDateTime(QuickTimeTrackHeaderDirectory.TagCreated, out dateTime)) results.Add(dateTime); } - DateTime[] filtered = year is null ? results.ToArray() : (from l in results where l.Year >= year select l).ToArray(); - if (filtered.Any()) - result = filtered.Min(); - else if (results.Any()) + if (results.Any()) result = results.Min(); else result = null; diff --git a/Move-By-Id/MoveById.cs b/Move-By-Id/MoveById.cs index 83e7783..84c9b60 100644 --- a/Move-By-Id/MoveById.cs +++ b/Move-By-Id/MoveById.cs @@ -128,7 +128,7 @@ public class MoveById if (nameWithoutExtensionIsIdFormat) continue; } - (dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); + (_, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); if (id is null) continue; matches = (from l in allFiles where l.Contains($"{id}{fileHolder.ExtensionLowered}") select l).ToArray(); diff --git a/Rename/Models/AppSettings.cs b/Rename/Models/AppSettings.cs index bb90b9e..7f3a7d3 100644 --- a/Rename/Models/AppSettings.cs +++ b/Rename/Models/AppSettings.cs @@ -8,7 +8,6 @@ public class AppSettings public string Company { init; get; } public string ComparePathsFile { init; get; } - public string CopyTo { init; get; } public int MaxDegreeOfParallelism { init; get; } public int MaxMinutesDelta { init; get; } public bool RenameUndo { init; get; } @@ -17,7 +16,6 @@ public class AppSettings [JsonConstructor] public AppSettings(string company, string comparePathsFile, - string copyTo, int maxDegreeOfParallelism, int maxMinutesDelta, bool renameUndo, @@ -25,7 +23,6 @@ public class AppSettings { Company = company; ComparePathsFile = comparePathsFile; - CopyTo = copyTo; MaxDegreeOfParallelism = maxDegreeOfParallelism; MaxMinutesDelta = maxMinutesDelta; RenameUndo = renameUndo; diff --git a/Rename/Models/Binder/AppSettings.cs b/Rename/Models/Binder/AppSettings.cs index a56acd2..8237bd6 100644 --- a/Rename/Models/Binder/AppSettings.cs +++ b/Rename/Models/Binder/AppSettings.cs @@ -10,7 +10,6 @@ public class AppSettings public string Company { get; set; } public string ComparePathsFile { get; set; } - public string CopyTo { get; set; } public int? MaxDegreeOfParallelism { get; set; } public int? MaxMinutesDelta { get; set; } public bool? RenameUndo { get; set; } @@ -36,7 +35,6 @@ public class AppSettings result = new( appSettings.Company, appSettings.ComparePathsFile, - appSettings.CopyTo, appSettings.MaxDegreeOfParallelism.Value, appSettings.MaxMinutesDelta.Value, appSettings.RenameUndo.Value, diff --git a/Rename/Rename.cs b/Rename/Rename.cs index b0549a6..c435833 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -46,6 +46,7 @@ public class Rename throw new Exception("Nested isn't allowed!"); log.Information(propertyConfiguration.RootDirectory); Verify(); + log.Information(appSettings.ComparePathsFile); string json = File.ReadAllText(appSettings.ComparePathsFile); MatchNginx[]? matchNginxCollection = JsonSerializer.Deserialize(json); if (matchNginxCollection is null) @@ -70,6 +71,7 @@ public class Rename RenameByDateTaken(log, matchNginxCollection); else if (matchNginxCollection.Any()) { + log.Information(matchNginxCollection.First().ConvertedPath); List lines = RenameFilesInDirectories(log, matchNginxCollection); File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); if (comparePathRoot != Path.GetPathRoot(matchNginxCollection[0].ConvertedPath)) @@ -113,16 +115,20 @@ public class Rename } } - private static List<(FileHolder, string)> GetRenameUndoToDoCollection(ProgressBar progressBar, string[] files) + private static List<(FileHolder, string, string)> GetRenameUndoToDoCollection(ProgressBar progressBar, string[] files) { - List<(FileHolder, string)> results = new(); + List<(FileHolder, string, string)> results = new(); string[] lines; string fileName; + string? directory; FileHolder fileHolder; List distinct = new(); foreach (string file in files) { progressBar.Tick(); + directory = Path.GetDirectoryName(file); + if (string.IsNullOrEmpty(directory)) + continue; fileName = Path.GetFileName(file); if (!fileName.EndsWith(".id")) continue; @@ -133,49 +139,56 @@ public class Rename continue; distinct.Add(lines[1]); fileHolder = new(lines[0]); - results.Add(new(fileHolder, lines[1])); + results.Add(new(fileHolder, directory, lines[1])); } return results; } - private List<(FileHolder, string)> GetToDoCollection(ProgressBar progressBar, string[] files) + private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, string[] files) { - List<(FileHolder, string)> results = new(); + List<(FileHolder, string, string)> results = new(); int? id; - string fileName; + int season; string? message; string checkFile; + DateTime dateTime; + string seasonName; string? directory; - TimeSpan timeSpan; - DateTime? dateTime; + TimeSpan? timeSpan; DateTime?[] dateTimes; FileHolder fileHolder; string[]? ffmpegFiles; + string seasonDirectory; bool isIgnoreExtension; - string checkFileExtension; - DateTime? minimumDateTime; const string jpg = ".jpg"; + DateTime? minimumDateTime; + string checkFileExtension; + DateTime? dateTimeFromName; + DateTime? dateTimeOriginal; const string jpeg = ".jpeg"; List distinct = new(); bool isValidImageFormatExtension; bool nameWithoutExtensionIsIdFormat; + DateTime? metadataMinimumDateTime = null; IReadOnlyList directories; foreach (string file in files) { progressBar.Tick(); fileHolder = new(file); + if (!fileHolder.Exists) + continue; + directory = Path.GetDirectoryName(file); + if (string.IsNullOrEmpty(directory)) + continue; if (file.EndsWith(".rename")) { - directory = Path.GetDirectoryName(file); - if (string.IsNullOrEmpty(directory)) - continue; checkFile = Path.Combine(directory, $"rename_{Path.GetFileName(file[..^7])}"); if (File.Exists(checkFile)) continue; if (distinct.Contains(checkFile)) continue; distinct.Add(checkFile); - results.Add(new(fileHolder, checkFile)); + results.Add(new(fileHolder, directory, checkFile)); continue; } if (file.EndsWith(".jpg.del")) @@ -186,7 +199,7 @@ public class Rename if (distinct.Contains(checkFile)) continue; distinct.Add(checkFile); - results.Add(new(fileHolder, checkFile)); + results.Add(new(fileHolder, directory, checkFile)); continue; } if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null) @@ -224,9 +237,9 @@ public class Rename if (fileHolder.DirectoryName is null) continue; } - if (!isIgnoreExtension && isValidImageFormatExtension) + if (fileHolder.ExtensionLowered == jpeg) { - if (fileHolder.ExtensionLowered == jpeg) + if (!isIgnoreExtension && isValidImageFormatExtension) { if (File.Exists($"{fileHolder.FullName}.id")) { @@ -236,7 +249,7 @@ public class Rename if (distinct.Contains(checkFile)) continue; distinct.Add(checkFile); - results.Add(new(new($"{fileHolder.FullName}.id"), checkFile)); + results.Add(new(new($"{fileHolder.FullName}.id"), directory, checkFile)); } checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}"); if (File.Exists(checkFile)) @@ -244,7 +257,7 @@ public class Rename if (distinct.Contains(checkFile)) continue; distinct.Add(checkFile); - results.Add(new(fileHolder, checkFile)); + results.Add(new(fileHolder, directory, checkFile)); if (File.Exists(checkFile)) continue; File.Move(fileHolder.FullName, checkFile); @@ -253,70 +266,76 @@ public class Rename continue; } } - (dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); + dateTimeFromName = Shared.Models.Stateless.Methods.IProperty.GetDateTimeFromName(fileHolder); + (dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); minimumDateTime = dateTimes.Min(); - if (minimumDateTime is null || !isIgnoreExtension && isValidImageFormatExtension) - { - dateTime = Shared.Models.Stateless.Methods.IProperty.GetDateTimeFromName(fileHolder); - if (dateTime is null || minimumDateTime is null) - timeSpan = new TimeSpan(0); - else - timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - dateTime.Value.Ticks)); - } + if (minimumDateTime is null) + break; + if (dateTimeOriginal is not null && dateTimeFromName is not null) + timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - new long[] { dateTimeOriginal.Value.Ticks, dateTimeFromName.Value.Ticks }.Min())); + else if (dateTimeFromName is not null) + timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - dateTimeFromName.Value.Ticks)); + else if (dateTimeOriginal is not null) + timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - dateTimeOriginal.Value.Ticks)); else { - fileName = Path.GetFileName(fileHolder.DirectoryName); - if (fileName.Length < 4 || !int.TryParse(fileName[..4], out int year)) - year = minimumDateTime.Value.Year; if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered)) continue; try { directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(file); } catch (Exception) { continue; } - dateTime = Metadata.Models.Stateless.Methods.IMetadata.GetMinimumDateTime(dateTimes, year, directories); - timeSpan = new TimeSpan(int.MaxValue); + metadataMinimumDateTime = Metadata.Models.Stateless.Methods.IMetadata.GetMinimumDateTime(directories); + if (metadataMinimumDateTime is null) + timeSpan = null; + else + timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - metadataMinimumDateTime.Value.Ticks)); } - if (dateTime is not null && string.IsNullOrEmpty(_AppSettings.CopyTo) && timeSpan.TotalMinutes > _AppSettings.MaxMinutesDelta) + if (timeSpan is null || timeSpan.Value.TotalMinutes >= _AppSettings.MaxMinutesDelta) { + if (metadataMinimumDateTime is null) + break; checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; - checkFile = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks}.{fileHolder.Length}{checkFileExtension}"); + checkFile = Path.Combine(fileHolder.DirectoryName, $"{metadataMinimumDateTime.Value:yyyy-MM-dd}.{metadataMinimumDateTime.Value.Ticks}.{fileHolder.Length}{checkFileExtension}"); if (checkFile == fileHolder.FullName) continue; if (distinct.Contains(checkFile)) continue; distinct.Add(checkFile); - results.Add(new(fileHolder, checkFile)); + results.Add(new(fileHolder, directory, checkFile)); if (ffmpegFiles is not null) { foreach (string ffmpegFile in ffmpegFiles) File.Delete(ffmpegFile); } - continue; } - if (id is null) - continue; - if (ffmpegFiles is not null) + else { - foreach (string ffmpegFile in ffmpegFiles) - File.Delete(ffmpegFile); - fileHolder = new(file); - if (fileHolder.DirectoryName is null) + if (id is null) + continue; + dateTime = minimumDateTime.Value.AddTicks(timeSpan.Value.Ticks); + (season, seasonName) = Shared.Models.Stateless.Methods.IProperty.GetSeason(dateTime.DayOfYear); + seasonDirectory = Path.Combine(fileHolder.DirectoryName, $"{dateTime.Year}.{season} {seasonName}"); + if (ffmpegFiles is not null) + { + foreach (string ffmpegFile in ffmpegFiles) + File.Delete(ffmpegFile); + fileHolder = new(file); + } + checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; + checkFile = Path.Combine(seasonDirectory, $"{id.Value}{checkFileExtension}"); + if (checkFile == fileHolder.FullName) continue; - } - checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; - checkFile = Path.Combine(fileHolder.DirectoryName, $"{id.Value}{checkFileExtension}"); - if (checkFile == fileHolder.FullName) - continue; - if (File.Exists(checkFile)) - { - checkFile = string.Concat(checkFile, ".del"); if (File.Exists(checkFile)) + { + checkFile = string.Concat(checkFile, ".del"); + if (File.Exists(checkFile)) + continue; + } + if (distinct.Contains(checkFile)) continue; + distinct.Add(checkFile); + results.Add(new(fileHolder, seasonDirectory, checkFile)); } - if (distinct.Contains(checkFile)) - continue; - distinct.Add(checkFile); - results.Add(new(fileHolder, checkFile)); } return results; } @@ -392,49 +411,6 @@ public class Rename } } - private List CopyInstead(ILogger log, List<(FileHolder, string)> verifiedToDoCollection) - { - List results = new(); - string copyTo; - string? directory; - ConsoleKey? consoleKey = null; - List distinctDirectories = new(); - List<(FileHolder, string)> copyCollection = new(); - foreach ((FileHolder fileHolder, string to) in verifiedToDoCollection) - { - copyTo = $"{_AppSettings.CopyTo}{to[1..]}"; - directory = Path.GetDirectoryName(copyTo); - if (directory is null) - continue; - copyCollection.Add(new(fileHolder, copyTo)); - if (distinctDirectories.Contains(directory)) - continue; - distinctDirectories.Add(directory); - } - CreateDirectories(distinctDirectories); - log.Information($"Ready to Copy {verifiedToDoCollection.Count} file(s)?"); - for (int y = 0; y < int.MaxValue; y++) - { - log.Information("Press \"Y\" key to copy file(s), \"N\" key to log file(s) or close console to not copy files"); - consoleKey = System.Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - log.Information(". . ."); - if (consoleKey is null || consoleKey.Value != ConsoleKey.Y) - log.Information("Nothing Copied!"); - else - { - foreach ((FileHolder fileHolder, string to) in verifiedToDoCollection) - { - results.Add(fileHolder.NameWithoutExtension); - File.Copy(fileHolder.FullName, to); - } - log.Information("Done Copying"); - } - return results; - } - private static List Move(ILogger log, List<(FileHolder, string)> verifiedToDoCollection) { List results = new(); @@ -471,12 +447,14 @@ public class Rename string message; List allFiles; ProgressBar progressBar; - List<(FileHolder, string)> toDoCollection; + List distinctDirectories = new(); allFiles = GetAllFiles(matchNginxCollection); + List<(FileHolder, string, string)> toDoCollection; List<(FileHolder, string)> verifiedToDoCollection; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; for (int i = 1; i < 3; i++) { + distinctDirectories.Clear(); if (!allFiles.Any()) continue; message = $"{i}) Renaming files"; @@ -491,20 +469,27 @@ public class Rename else toDoCollection = GetRenameUndoToDoCollection(progressBar, files); verifiedToDoCollection = new(); - foreach ((FileHolder fileHolder, string to) in toDoCollection) + foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) + { + if (distinctDirectories.Contains(directory)) + continue; + distinctDirectories.Add(directory); + } + foreach (string distinctDirectory in distinctDirectories) + { + if (!Directory.Exists(distinctDirectory)) + _ = Directory.CreateDirectory(distinctDirectory); + } + foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) { if (File.Exists(to)) continue; verifiedToDoCollection.Add(new(fileHolder, to)); - if (string.IsNullOrEmpty(_AppSettings.CopyTo)) - File.WriteAllText($"{to}.id", $"{to}{Environment.NewLine}{fileHolder.FullName}"); + File.WriteAllText($"{to}.id", $"{to}{Environment.NewLine}{fileHolder.FullName}"); } if (!verifiedToDoCollection.Any()) continue; - if (string.IsNullOrEmpty(_AppSettings.CopyTo)) - results.AddRange(Move(log, verifiedToDoCollection)); - else - results.AddRange(CopyInstead(log, verifiedToDoCollection)); + results.AddRange(Move(log, verifiedToDoCollection)); allFiles = GetAllFiles(matchNginxCollection); progressBar.Dispose(); } diff --git a/Rename/appsettings.json b/Rename/appsettings.json index 088fcfb..7505b59 100644 --- a/Rename/appsettings.json +++ b/Rename/appsettings.json @@ -1,7 +1,6 @@ { "ComparePathsFile": "", "Company": "Mike Phares", - "CopyTo": "", "Linux": {}, "Logging": { "LogLevel": { diff --git a/Shared/Models/Stateless/Methods/IProperty.cs b/Shared/Models/Stateless/Methods/IProperty.cs index 11cfcf0..824315a 100644 --- a/Shared/Models/Stateless/Methods/IProperty.cs +++ b/Shared/Models/Stateless/Methods/IProperty.cs @@ -46,9 +46,9 @@ public interface IProperty static (bool?, string[]) IsWrongYear(Models.FileHolder fileHolder, DateTime? dateTimeOriginal, List dateTimes) => Property.IsWrongYear(fileHolder, dateTimeOriginal, dateTimes); - (DateTime?[], int?, string?) TestStatic_Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) => + (DateTime?, DateTime?[], int?, string?) TestStatic_Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) => Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); - static (DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) => + static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) => Property.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); DateTime? TestStatic_GetDateTimeFromName(Models.FileHolder fileHolder) => diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index 7958af8..82d09a9 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -366,7 +366,7 @@ internal abstract class Property #pragma warning disable CA1416 - internal static (DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) + internal static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) { int? id = null; string? message = null; @@ -451,7 +451,7 @@ internal abstract class Property } } DateTime?[] dateTimes = new DateTime?[] { fileHolder.LastWriteTime, fileHolder.CreationTime, dateTime, dateTimeDigitized, dateTimeOriginal, gpsDateStamp }; - return new(dateTimes, id, message); + return new(dateTimeOriginal, dateTimes, id, message); } #pragma warning restore CA1416