Works better now

This commit is contained in:
Holger Börchers 2022-12-01 17:08:03 +01:00
parent e705d0d286
commit 182813bd21
6 changed files with 43 additions and 46 deletions

View File

@ -2,7 +2,7 @@
public static class FilesHelper public static class FilesHelper
{ {
private static readonly string[] SupportedFileExtensions = { ".jpg", ".cr2", ".mp4" }; private static readonly string[] SupportedFileExtensions = { ".jpg", ".cr2", ".mp4", ".mov" };
public static IEnumerable<string> FindSupportedFilesRecursively(string path) public static IEnumerable<string> FindSupportedFilesRecursively(string path)
{ {
@ -10,8 +10,6 @@ public static class FilesHelper
foreach (var file in files) foreach (var file in files)
{ {
var fileExt = Path.GetExtension(file); var fileExt = Path.GetExtension(file);
if (fileExt is null)
continue;
foreach (var supportedFileExtension in SupportedFileExtensions) foreach (var supportedFileExtension in SupportedFileExtensions)
{ {
if (fileExt.Equals(supportedFileExtension, StringComparison.InvariantCultureIgnoreCase)) if (fileExt.Equals(supportedFileExtension, StringComparison.InvariantCultureIgnoreCase))

View File

@ -22,7 +22,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" /> <PackageReference Include="Spectre.Console" Version="0.45.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -16,7 +16,7 @@ internal static class Program
try try
{ {
var renamer = new Renamer(configuration); var renamer = new Renamer(configuration);
return renamer.Run(); return renamer.RunAsync().GetAwaiter().GetResult();
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -1,16 +1,16 @@
using MetadataExtractor; using System.Runtime.InteropServices.JavaScript;
using MetadataExtractor;
using MetadataExtractor.Formats.Exif; using MetadataExtractor.Formats.Exif;
using MetadataExtractor.Formats.QuickTime; using MetadataExtractor.Formats.QuickTime;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Serilog; using Serilog;
using ShellProgressBar; using Spectre.Console;
using Directory = System.IO.Directory; using Directory = System.IO.Directory;
namespace PhotoRenamer; namespace PhotoRenamer;
internal class Renamer internal class Renamer
{ {
private readonly ProgressBarOptions _childOptions;
private readonly string _sourcePath; private readonly string _sourcePath;
private readonly string _targetPath; private readonly string _targetPath;
private int _currentCount; private int _currentCount;
@ -21,51 +21,52 @@ internal class Renamer
_targetPath = Path.GetFullPath(configuration["Target"]); _targetPath = Path.GetFullPath(configuration["Target"]);
Log.Information($"Source path: {_sourcePath}"); Log.Information($"Source path: {_sourcePath}");
Log.Information($"Target path: {_targetPath}"); Log.Information($"Target path: {_targetPath}");
_childOptions = new ProgressBarOptions
{
ForegroundColor = ConsoleColor.Yellow,
BackgroundColor = ConsoleColor.DarkGreen,
ProgressCharacter = '─',
CollapseWhenFinished = true
};
} }
public int Run() public async Task<int> RunAsync()
{ {
var files = Directory.GetFiles(_sourcePath, "*", SearchOption.AllDirectories); var files = Directory.GetFiles(_sourcePath, "*", SearchOption.AllDirectories);
var options = new ProgressBarOptions
{
ForegroundColor = ConsoleColor.Yellow,
ForegroundColorDone = ConsoleColor.DarkGreen,
BackgroundColor = ConsoleColor.DarkGray,
BackgroundCharacter = '\u2593'
};
_currentCount = 0; _currentCount = 0;
using var progressBar = new ProgressBar(files.Length, "Copying files", options); var po = new ParallelOptions { MaxDegreeOfParallelism = 3 };
var po = new ParallelOptions { MaxDegreeOfParallelism = 1 }; await AnsiConsole
.Progress()
Parallel.ForEach(files, po, file => Body(file, progressBar)); .StartAsync(async ctx =>
{
await Parallel.ForEachAsync(files, po, (s, token) => Body(s, ctx, token));
});
return 0; 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 try
{ {
var directories = ImageMetadataReader.ReadMetadata(file); DateTime dateTime;
var dateTime = GetDateTimeFromExif(directories) ?? GetDateTimeFromMp4(directories) ?? GetDateTimeFromLastWrite(file); 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); var folder = CreateFolder(dateTime);
CopyFile(folder, file, progressBar); var progress = new Progress<double>(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 finally
{ {
Interlocked.Increment(ref _currentCount); Interlocked.Increment(ref _currentCount);
progressBar.Tick(_currentCount); task.StopTask();
} }
} }
@ -93,24 +94,22 @@ internal class Renamer
destination.CreationTimeUtc = source.CreationTimeUtc; destination.CreationTimeUtc = source.CreationTimeUtc;
} }
private async void CopyFile(string folder, string file, ProgressBarBase progressBar) private static async Task CopyFileAsync(string folder, string file, IProgress<double>? progress = null)
{ {
var destination = new FileInfo(Path.Combine(folder, Path.GetFileName(file))); var destination = new FileInfo(Path.Combine(folder, Path.GetFileName(file)));
var source = new FileInfo(file); var source = new FileInfo(file);
if (destination.Exists && destination.Length == source.Length) if (destination.Exists && destination.Length == source.Length)
{
progress?.Report(1);
return; 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 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); await using var targetStream = File.Open(destination.FullName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
var progress = new Progress<long>(o => progressBar.Tick((int)o * 100)); await sourceStream.CopyToAsync(targetStream, 81920, progress: progress);
await sourceStream.CopyToAsync(targetStream, 81920, progress);
ResetTimes(destination, source); ResetTimes(destination, source);
child.Tick(100);
} }
private string CreateFolder(DateTime dateTime) private string CreateFolder(DateTime dateTime)

View File

@ -2,7 +2,7 @@
public static class StreamExtensions public static class StreamExtensions
{ {
public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long>? progress = null, CancellationToken cancellationToken = default) public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<double>? progress = null, CancellationToken cancellationToken = default)
{ {
if (source == null) if (source == null)
throw new ArgumentNullException(nameof(source)); throw new ArgumentNullException(nameof(source));
@ -22,7 +22,7 @@ public static class StreamExtensions
{ {
await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
progress?.Report(totalBytesRead); progress?.Report(totalBytesRead / (double)source.Length);
} }
} }
} }

View File

@ -1,4 +1,4 @@
{ {
"Source": "D:\\Nextcloud2\\Upload", "Source": "C:\\Users\\Holger\\Nextcloud\\DCIM",
"Target": "D:\\UploadX" "Target": "C:\\Users\\Holger\\Nextcloud\\DCIM"
} }