diff --git a/PhotoRenamer/FilesHelper.cs b/PhotoRenamer/FilesHelper.cs index 42c4ef1..2f03242 100644 --- a/PhotoRenamer/FilesHelper.cs +++ b/PhotoRenamer/FilesHelper.cs @@ -2,7 +2,7 @@ public static class FilesHelper { - private static readonly string[] SupportedFileExtensions = { ".jpg", ".cr2", ".mp4" }; + private static readonly string[] SupportedFileExtensions = { ".jpg", ".cr2", ".mp4", ".mov" }; public static IEnumerable FindSupportedFilesRecursively(string path) { @@ -10,8 +10,6 @@ public static class FilesHelper foreach (var file in files) { var fileExt = Path.GetExtension(file); - if (fileExt is null) - continue; foreach (var supportedFileExtension in SupportedFileExtensions) { if (fileExt.Equals(supportedFileExtension, StringComparison.InvariantCultureIgnoreCase)) diff --git a/PhotoRenamer/PhotoRenamer.csproj b/PhotoRenamer/PhotoRenamer.csproj index 302592d..e6d48c2 100644 --- a/PhotoRenamer/PhotoRenamer.csproj +++ b/PhotoRenamer/PhotoRenamer.csproj @@ -22,7 +22,7 @@ - + diff --git a/PhotoRenamer/Program.cs b/PhotoRenamer/Program.cs index 8bf7e34..3980de5 100644 --- a/PhotoRenamer/Program.cs +++ b/PhotoRenamer/Program.cs @@ -16,7 +16,7 @@ internal static class Program try { var renamer = new Renamer(configuration); - return renamer.Run(); + return renamer.RunAsync().GetAwaiter().GetResult(); } catch (Exception e) { diff --git a/PhotoRenamer/Renamer.cs b/PhotoRenamer/Renamer.cs index 8b3cf56..0b96bfd 100644 --- a/PhotoRenamer/Renamer.cs +++ b/PhotoRenamer/Renamer.cs @@ -1,16 +1,16 @@ -using MetadataExtractor; +using System.Runtime.InteropServices.JavaScript; +using MetadataExtractor; using MetadataExtractor.Formats.Exif; using MetadataExtractor.Formats.QuickTime; using Microsoft.Extensions.Configuration; using Serilog; -using ShellProgressBar; +using Spectre.Console; using Directory = System.IO.Directory; namespace PhotoRenamer; internal class Renamer { - private readonly ProgressBarOptions _childOptions; private readonly string _sourcePath; private readonly string _targetPath; private int _currentCount; @@ -21,51 +21,52 @@ internal class Renamer _targetPath = Path.GetFullPath(configuration["Target"]); Log.Information($"Source path: {_sourcePath}"); Log.Information($"Target path: {_targetPath}"); - _childOptions = new ProgressBarOptions - { - ForegroundColor = ConsoleColor.Yellow, - BackgroundColor = ConsoleColor.DarkGreen, - ProgressCharacter = '─', - CollapseWhenFinished = true - }; } - public int Run() + public async Task RunAsync() { var files = Directory.GetFiles(_sourcePath, "*", SearchOption.AllDirectories); - var options = new ProgressBarOptions - { - ForegroundColor = ConsoleColor.Yellow, - ForegroundColorDone = ConsoleColor.DarkGreen, - BackgroundColor = ConsoleColor.DarkGray, - BackgroundCharacter = '\u2593' - }; _currentCount = 0; - using var progressBar = new ProgressBar(files.Length, "Copying files", options); - var po = new ParallelOptions { MaxDegreeOfParallelism = 1 }; - - Parallel.ForEach(files, po, file => Body(file, progressBar)); - + var po = new ParallelOptions { MaxDegreeOfParallelism = 3 }; + await AnsiConsole + .Progress() + .StartAsync(async ctx => + { + await Parallel.ForEachAsync(files, po, (s, token) => Body(s, ctx, token)); + }); return 0; } - private void Body(string file, ProgressBar progressBar) + private async ValueTask Body(string file, ProgressContext progressContext, CancellationToken token) { + var task = progressContext.AddTask($"[green]{file}[/]"); try { - var directories = ImageMetadataReader.ReadMetadata(file); - var dateTime = GetDateTimeFromExif(directories) ?? GetDateTimeFromMp4(directories) ?? GetDateTimeFromLastWrite(file); + DateTime dateTime; + try + { + var directories = ImageMetadataReader.ReadMetadata(file); + dateTime = GetDateTimeFromExif(directories) ?? GetDateTimeFromMp4(directories) ?? GetDateTimeFromLastWrite(file); + } + catch (ImageProcessingException e) + { + Log.Error(e, $"Error reading file information from {file}"); + dateTime = GetDateTimeFromLastWrite(file); + } + var folder = CreateFolder(dateTime); - CopyFile(folder, file, progressBar); + var progress = new Progress(v => task.Value = v * 100); + + await CopyFileAsync(folder, file, progress); } - catch (ImageProcessingException) + catch (Exception ex) { - //silently ignore + Log.Error(ex, "Error reading file information"); } finally { Interlocked.Increment(ref _currentCount); - progressBar.Tick(_currentCount); + task.StopTask(); } } @@ -93,24 +94,22 @@ internal class Renamer destination.CreationTimeUtc = source.CreationTimeUtc; } - private async void CopyFile(string folder, string file, ProgressBarBase progressBar) + private static async Task CopyFileAsync(string folder, string file, IProgress? progress = null) { var destination = new FileInfo(Path.Combine(folder, Path.GetFileName(file))); var source = new FileInfo(file); if (destination.Exists && destination.Length == source.Length) + { + progress?.Report(1); return; - - using var child = progressBar.Spawn(100, destination.FullName, _childOptions); + } await using var sourceStream = File.Open(source.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); await using var targetStream = File.Open(destination.FullName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); - var progress = new Progress(o => progressBar.Tick((int)o * 100)); - await sourceStream.CopyToAsync(targetStream, 81920, progress); + await sourceStream.CopyToAsync(targetStream, 81920, progress: progress); ResetTimes(destination, source); - - child.Tick(100); } private string CreateFolder(DateTime dateTime) diff --git a/PhotoRenamer/StreamExtensions.cs b/PhotoRenamer/StreamExtensions.cs index 7c1a936..7669bd0 100644 --- a/PhotoRenamer/StreamExtensions.cs +++ b/PhotoRenamer/StreamExtensions.cs @@ -2,7 +2,7 @@ public static class StreamExtensions { - public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress? progress = null, CancellationToken cancellationToken = default) + public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress? progress = null, CancellationToken cancellationToken = default) { if (source == null) throw new ArgumentNullException(nameof(source)); @@ -22,7 +22,7 @@ public static class StreamExtensions { await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); totalBytesRead += bytesRead; - progress?.Report(totalBytesRead); + progress?.Report(totalBytesRead / (double)source.Length); } } } diff --git a/PhotoRenamer/appsettings.json b/PhotoRenamer/appsettings.json index c2e8346..89d5e66 100644 --- a/PhotoRenamer/appsettings.json +++ b/PhotoRenamer/appsettings.json @@ -1,4 +1,4 @@ { - "Source": "D:\\Nextcloud2\\Upload", - "Target": "D:\\UploadX" + "Source": "C:\\Users\\Holger\\Nextcloud\\DCIM", + "Target": "C:\\Users\\Holger\\Nextcloud\\DCIM" } \ No newline at end of file