trevor1940
asked on
C#: Renaming jpg's to match a corrisponding video file
Hi
I'm trying to search a given directory for video and jpg files matching / renaming the jpg to the video
If a video file has a jpg with the same name I can skip it
else I want the user to choose from the list within the directory by typing the associated number or a completely new option / x (for no jpg)
in my test folder I have
File01.mp4
File02.mkv
File01.jpg
pic.jpg
SubFold
File01.jpg
File03.mp4
File03.mp4_snapshot_18.48_ 2019.06.03 _19.50.59. jpg
File04.mp4
File04.jpg
File05.mp4
File garbish5.jpg
In the code bellow
First I'm not listing the top level directory only SubFold
Second how do I alow the users chose with the jpg file so I can rename it but filter out the jpg's that already have a video
(Top folder don't show File01.jpg because of File01.mp4 SubFold Show File01.jpg, File03.mp4_snapshot_18.48_ 2019.06.03 _19.50.59. jpg & File garbish5.jpg )
once the jpg has been rename this is no longer an option)
Some jpg files could be Auto renamed like "File03.mp4_snapshot_18.48 _2019.06.0 3_19.50.59 .jpg" but for now I just need to the manual choice
I'm trying to search a given directory for video and jpg files matching / renaming the jpg to the video
If a video file has a jpg with the same name I can skip it
else I want the user to choose from the list within the directory by typing the associated number or a completely new option / x (for no jpg)
in my test folder I have
File01.mp4
File02.mkv
File01.jpg
pic.jpg
SubFold
File01.jpg
File03.mp4
File03.mp4_snapshot_18.48_
File04.mp4
File04.jpg
File05.mp4
File garbish5.jpg
In the code bellow
First I'm not listing the top level directory only SubFold
Second how do I alow the users chose with the jpg file so I can rename it but filter out the jpg's that already have a video
(Top folder don't show File01.jpg because of File01.mp4 SubFold Show File01.jpg, File03.mp4_snapshot_18.48_
once the jpg has been rename this is no longer an option)
Some jpg files could be Auto renamed like "File03.mp4_snapshot_18.48
using System.IO;
namespace Kodi
{
class Program
{
static void Main(string[] args)
{
string BaseFold = "";
string Ans;
if(args == null)
{
Console.WriteLine("Drag a Folder to search");
Ans = Console.ReadLine();
BaseFold = Ans;
}
else
{
BaseFold = args[0];
}
Console.WriteLine("You chose {0}", BaseFold);
if (BaseFold.EndsWith(@""""))
{
BaseFold = BaseFold.Trim(new char[] { '"' });
Console.WriteLine("trimed " + BaseFold);
}
if (Directory.Exists(BaseFold))
{
// Get dirs recursively
string[] folders = Directory.GetDirectories(BaseFold, "*", SearchOption.AllDirectories);
foreach (string folder in folders)
{
FileInfo DI = new FileInfo(folder);
String dirName = DI.Directory.Name;
Console.WriteLine(dirName);
if (dirName == "used" || dirName == "pics" )
{
continue;
}
var Files = Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".mp4") || s.EndsWith(".mkv") || s.EndsWith(".wmv"));
foreach (string VidFile in Files)
{
FileInfo FI = new FileInfo(VidFile);
string VidName = FI.Name;
var VidDate = FI.LastWriteTime;
string jpgExist = folder + "\\" + VidName + ".jpg";
if (File.Exists(jpgExist))
{
continue;
}
else
{
Console.WriteLine("Choose a jpg to go with\n{0} date {1} or x for none\n", VidName, VidDate);
var jpgFiles = Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".jpg"));
int Count = 0;
foreach(string jpgFile in jpgFiles)
{
FileInfo JI = new FileInfo(jpgFile);
string Jname = JI.Name;
var Jdate = JI.LastWriteTime;
Console.WriteLine("{0} {1} {2}", Count, Jname, Jdate );
Count++;
}
}
}
}
}
Console.ReadLine();
}
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Any particular reason you're trying to do this as a console application? Seems like the user experience would be so much easier with a WinForms app w/ a ListBox to choose the match from...
Wait, are you saying that you -want- the top folder contents listed?
Right now, you have:
string[] folders = Directory.GetDirectories(B aseFold, "*", SearchOption.AllDirectorie s);
...which returns all the subfolders inside BaseFold, and then you are looping through that "folders" array. So if you want to include "BaseFold" in the list of folders to loop through, then just add it to "folders". Just add this right below your "string[] folders..." line:
For the JPG selection, I'd strongly recommend what Mike is saying - the best UI is going to come from a ListBox. Otherwise, if you have a lot of options to select from, it's going to become really cumbersome to use.
Otherwise, if you need to stick with the console, you already have most of the pieces in place - the Console.ReadLine() call will give you input. Just convert jpgFiles to an array so you have numeric indexing, then output the jpgFile options, prompt the user for selection, and process the response.
Step 1: Convert jpgFiles to an array
BEFORE: var jpgFiles = Directory.EnumerateFiles(f older, "*", SearchOption.TopDirectoryO nly).Where (s => s.EndsWith(".jpg"));
AFTER: var jpgFiles = Directory.EnumerateFiles(f older, "*", SearchOption.TopDirectoryO nly).Where (s => s.EndsWith(".jpg")).ToArray();
Step 2: Loop through jpgFiles and output as options:
Step 3: Parse the input
Step 4: Handle the selection
I haven't actually tried the above code, but it should work in theory.
Right now, you have:
string[] folders = Directory.GetDirectories(B
...which returns all the subfolders inside BaseFold, and then you are looping through that "folders" array. So if you want to include "BaseFold" in the list of folders to loop through, then just add it to "folders". Just add this right below your "string[] folders..." line:
Array.Resize(ref folders, folders.Length+1);
folders[[folders.Length - 1] = BaseFold;
For the JPG selection, I'd strongly recommend what Mike is saying - the best UI is going to come from a ListBox. Otherwise, if you have a lot of options to select from, it's going to become really cumbersome to use.
Otherwise, if you need to stick with the console, you already have most of the pieces in place - the Console.ReadLine() call will give you input. Just convert jpgFiles to an array so you have numeric indexing, then output the jpgFile options, prompt the user for selection, and process the response.
Step 1: Convert jpgFiles to an array
BEFORE: var jpgFiles = Directory.EnumerateFiles(f
AFTER: var jpgFiles = Directory.EnumerateFiles(f
Step 2: Loop through jpgFiles and output as options:
Console.WriteLine("Choose an option:");
for(int i = 0; i < jpgFiles.Length; i++)
{
Console.WriteLine(i + 1 + ". " + jpgFiles[i]);
}
Console.WriteLine("Or type 0 to exit.");
Step 3: Parse the input
// Prompt for user selection and keep prompting until we get a valid one
int userSelection = -1;
while(true)
{
if(int.TryParse(Console.ReadLine(), out userSelection))
{
// User input was between 0 (exit) and the last option in the JPG files array
if ((userSelection >= 0) && (userSelection <= jpgFiles.Length))
{
break;
}
}
else
{
Console.WriteLine("Invalid option. Please try again.");
}
}
Step 4: Handle the selection
// Since we used 0 for Exit, subtract 1 so that -1 becomes Exit and userSelection aligns with our 0-based array index
userSelection--;
if(userSelection == -1)
{
// Code to exit
return;
}
else
{
// JPG option
string selectedJpgFile = jpgFiles[userSelection];
// Do with it as you will...
}
I haven't actually tried the above code, but it should work in theory.
ASKER
Thanx gr8gonzo I assumed
string[] folders = Directory.GetDirectories(B aseFold, "*", SearchOption.AllDirectorie s);
Meant everything
Today I've been playing with your Dictionary idea which could be the way forward
As for the UI
Within a listview can you have two columns Videos and JPG's then drag & drop the JPG 's to sort?
The end result would be per directory a 2 column sorted list with the Video and matching JPG per row
string[] folders = Directory.GetDirectories(B
Meant everything
Today I've been playing with your Dictionary idea which could be the way forward
As for the UI
Within a listview can you have two columns Videos and JPG's then drag & drop the JPG 's to sort?
The end result would be per directory a 2 column sorted list with the Video and matching JPG per row
Absolutely. You could also use a DataGridView instead of a ListView.
ASKER
As @gr8gonzo answered the opening question he wins
However I like Mikes idea so i'm going to look into it
However I like Mikes idea so i'm going to look into it
ASKER
Choosing which jpg goes with the video file
regular expressions could help with some however I need a mechanism where the user can pick from available jpg's in the same folder (Not already linked to a video) as sometimes the jpg's names have no relation to the associated video
I've written something similar in perl years ago then I pushed the options into an indexed array the user was shown the list and picked the number for whatever was the correct choice
Yes I will create a class once I've overcome this obstacle I intend to create kodi NFO files