My tool changes (depends on what file type a user chose) different media files' names to one qualified format yyyymmdd_hhmmss [optional desc].xxx:
- If it's an image, the date is taken from "Date Taken" property of the file.
- If it's an image and has a corresponding raw file, the date is taken from "Date Taken" property of the file and both image's and RAW's filenames are changed to qualified format.
- If it's an image that is already in qualified format and has a corresponding file with same name but with suffix ("20220209_111700.jpg" & "20220209_111700-1.jpg"), then delete the file without suffix and remove the suffix from second file.
- If it's a video without corresponding xml-meta file it should already have that format otherwise it's renamed to literrally YYYYMMDD_HHMMSS.mp4
- If it's a video file and has a xml-meta file, then the "Date Taken" is taken from that metadata file and both video's and metadata's filenames are changed to qualified format.
At first I decided to create a base class MediaFile and each type of file should implement ExtractDateTaken and Rename methods (see code below). Each specific type will find an associated file (raw file, or xml meta file, etc) so could be used later in Rename method. But, after reviewing the code I do not think that they should all inherit from same base class. Probably the ones without corresponding files should inherit from BaseClass1 and the rest from BaseClass2.
I included as much code as I could omitting irrelevant parts
public class Program
{
public static void Main(string[] args)
{
//very simplified way of c
var op = ArgumentParser.Parse(args);
if(op.Action == "photo-convert")
ConvertPhotoNames(...)
else if(op.Action == "video-convert")
ConvertVideoNames(...)
else if(op.Action == "modify-video-date")
ModifyVideoDate(...)
...
}
private static void ConvertPhotoNames(DirectoryInfo sourceDir)
{
var filesLoader = new PhotoFilesLoader();
// responsible to generate a name in case such file exists (e.g. adding (0))
var fileNameGenerator = new UniqueFileNameGenerator();
var fileNameHandler = new MediaFileNameHandler(filesLoader, fileNameGenerator);
fileNameHandler.ConvertName(sourceDir);
}
private static void ConvertMetaVideoNames(DirectoryInfo sourceDir)
{
var filesLoader = new MetaVideoFilesLoader();
var fileNameGenerator = new UniqueFileNameGenerator();
var fileNameHandler = new MediaFileNameHandler(filesLoader, fileNameGenerator);
fileNameHandler.ConvertName(sourceDir);
}
private static void ConvertVideoNames(DirectoryInfo sourceDir)
{
var filesLoader = new VideoFilesLoader();
var fileNameGenerator = new UniqueFileNameGenerator();
var fileNameHandler = new MediaFileNameHandler(filesLoader, fileNameGenerator);
fileNameHandler.ConvertName(sourceDir);
}
}
public class MediaFileNameHandler : IMediaFileNameHandler
{
public void ConvertName(DirectoryInfo sourceDir)
{
foreach (var file in _filesLoader.GetFiles(sourceDir))
{
if (!file.Name.IsQualifiedName)
{
if (file.ExtractDateTaken())
{
var newFileInfo = _fileNameGenerator.GenerateName(file);
file.Rename(newFileInfo.FullName);
}
}
}
}
}
public class QualifiedNameInfo
{
public bool IsQualifiedName { get; private set; }
public DateTime DateTaken { get; set; }
}
public abstract class MediaFile
{
public QualifiedNameInfo Name { get; private set; }
public abstract bool ExtractDateTaken();
public abstract void Rename(string destFileName);
public MediaFile(string filePath)
{
Name = new QualifiedNameInfo(filePath);
}
}
public class PhotoFile : MediaFile
{
public PhotoFile(string filePath)
{
//find all associated files
}
public override bool ExtractDateTaken()
{
// get DateTaken from file's DateTaken property
// Name.DateTaken = ...
}
}
public class VideoFile : MediaFile
{
public VideoFile(string filePath) {}
public override bool ExtractDateTaken()
{
// the file should already be in correct format
throw new NotImplementedException();
}
}
public class MetaVideoFile : MediaFile
{
public CameraVideoFile(string metaFile, string videoPath) {...}
public override bool ExtractDateTaken()
{
// get DateTaken from meta file
// Name.DateTaken = ...
}
}
public interface IMediaFilesLoader
{
IEnumerable<MediaFile> GetFiles(DirectoryInfo dir);
}
public class PhotoFilesLoader : IMediaFilesLoader
{
public IEnumerable<MediaFile> GetFiles(DirectoryInfo dir)
{
var factory = new MediaFileFactory();
var files = dir.EnumerateFiles()
.Where(f => f.Extension.IsImageExtension())
.Select(f => factory.Create(f.FullName));
return files;
}
}
public class VideoFilesLoader : IMediaFilesLoader
{
public IEnumerable<MediaFile> GetFiles(DirectoryInfo dir)
{
var factory = new MediaFileFactory();
var files = dir.EnumerateFiles()
.Where(f => f.Extension.IsVideoExtension())
.Select(f => factory.Create(f.FullName));
return files;
}
}
public class MetaVideoFilesLoader : IMediaFilesLoader
{
public IEnumerable<MediaFile> GetFiles(DirectoryInfo dir)
{
// [C0045M01.XML, C0045.MP4] - first 5 letters of meta filename is the filename of the video
foreach (var metaFile in dir.EnumerateFiles(".xml"))
{
var mp4Filename = metaFile.Name.Substring(0, 5);
var mp4File = new FileInfo(metaFile.DirectoryName "\\" mp4Filename ".mp4");
yield return new MetaVideoFile(metaFile, mp4File);
}
}
}
CodePudding user response:
