initial program
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
fix_subs
|
2
Makefile
Normal file
2
Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
fix_subs: fix_subs.cpp ezOptionParser.hpp
|
||||
g++ -std=c++20 -Wall -o fix_subs fix_subs.cpp ezOptionParser.hpp
|
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# fix-subs-in-nested-folders
|
||||
|
||||
Some shows will have their subtitles nested in a `Subs/` folder that is within the season itself. This causes some issues
|
||||
with Plex as it will not find the subtitles if they are nested. An example of this nested structure is:
|
||||
```
|
||||
/Show Name
|
||||
|- Season 01
|
||||
|- S01E01.mp4
|
||||
|- S01E02.mp4
|
||||
|- S01E03.mp4
|
||||
|- Subs/
|
||||
|- S01E01/
|
||||
|- Subtitle 1.srt
|
||||
|- Subtitle 2.srt
|
||||
|- S01E02/
|
||||
|- Subtitle 1.srt
|
||||
|- Subtitle 2.srt
|
||||
|- S01E03/
|
||||
|- Subtitle 1.srt
|
||||
|- Subtitle 2.srt
|
||||
|- Season 02
|
||||
|- S02E01.mp4
|
||||
|- S02E02.mp4
|
||||
|- S02E03.mp4
|
||||
|- Subs/
|
||||
|- S02E01/
|
||||
|- Subtitle 1.srt
|
||||
|- Subtitle 2.srt
|
||||
|- S02E02/
|
||||
|- Subtitle 1.srt
|
||||
|- Subtitle 2.srt
|
||||
|- S02E03/
|
||||
|- Subtitle 1.srt
|
||||
|- Subtitle 2.srt
|
||||
```
|
||||
|
||||
This short program will go through the folders and grab the subtitles files (.srt) and place them in the appropriate season folder.
|
||||
Plex should then be able to search for these subtitle files and load them correctly.
|
||||
|
||||
## Building
|
||||
Compile with C++20 using gcc:
|
||||
|
||||
```
|
||||
g++ -std=c++20 -o fix_subs fix_subs ezOptionParser.hpp
|
||||
```
|
||||
Or using the Makefile:
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
## Running
|
||||
You can simply run once it's compile using the flag `-f` to specify the top directory of the show.
|
||||
```
|
||||
./fix_subs -f "/home/daniel/Videos/Show Name/"
|
||||
```
|
2158
ezOptionParser.hpp
Normal file
2158
ezOptionParser.hpp
Normal file
File diff suppressed because it is too large
Load Diff
119
fix_subs.cpp
Normal file
119
fix_subs.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include "ezOptionParser.hpp"
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
//std::string path = "/mnt/z/Marvel's Daredevil (2015) [tvdb-281662]";
|
||||
|
||||
// args parser
|
||||
ez::ezOptionParser opt;
|
||||
opt.overview = "Fix subs in nested folders for TV show for Plex";
|
||||
opt.syntax = "fix_subs -f <FOLDER>";
|
||||
opt.add (
|
||||
"",
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
"PATH of the folder to be fixed.",
|
||||
"-f"
|
||||
);
|
||||
opt.parse(argc, argv);
|
||||
|
||||
if (opt.lastArgs.size() != 1)
|
||||
{
|
||||
std::cerr << "ERROR: Expected 1 argument, but got " << opt.lastArgs.size() << std::endl << std::endl;
|
||||
std::string usage;
|
||||
opt.getUsage(usage);
|
||||
std::cout << usage;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string path = *opt.lastArgs[0];
|
||||
|
||||
// remove trailing slash if there is one
|
||||
while (path.back() == '/')
|
||||
{
|
||||
path = path.substr(0, path.length()-1);
|
||||
}
|
||||
std::cout << "Path set to: " << path << std::endl << "Press ENTER to continue" << std::endl;
|
||||
std::cin.ignore();
|
||||
std::cout << "Beginning to fix subs folders..." << std::endl;
|
||||
// iterate through the top directory
|
||||
for (const auto &top_dir : std::filesystem::directory_iterator(path))
|
||||
{
|
||||
// if there are files in the top directory, ignore them
|
||||
if (std::filesystem::is_regular_file(top_dir.path()) == true)
|
||||
continue;
|
||||
|
||||
// only care for directories starting with 'Season'
|
||||
std::string folder_name = top_dir.path().filename();
|
||||
if (folder_name.starts_with("Season") == true)
|
||||
{
|
||||
std::string top_seasons_dir = top_dir.path();
|
||||
|
||||
// ensure "Subs" directory exists
|
||||
std::string seasons_dir_subs = top_seasons_dir + "/Subs";
|
||||
if (std::filesystem::exists(seasons_dir_subs) == true)
|
||||
{
|
||||
// interate through the seasons directories
|
||||
for (const auto &seasons_dir : std::filesystem::directory_iterator(top_dir.path()))
|
||||
{
|
||||
std::string item = seasons_dir.path();
|
||||
|
||||
// ignore txt files
|
||||
if (item.ends_with(".txt") == true || item.ends_with(".srt"))
|
||||
continue;
|
||||
|
||||
// only care about the files
|
||||
if (std::filesystem::is_regular_file(item) == true)
|
||||
{
|
||||
std::string full_episode_filename = seasons_dir.path().filename();
|
||||
|
||||
// strip extension from filename
|
||||
std::string episode_filename = full_episode_filename.substr(0, full_episode_filename.find_last_of("."));
|
||||
|
||||
// iterate through the season's subs folder
|
||||
std::string episode_sub_dir = seasons_dir_subs + "/" + episode_filename;
|
||||
|
||||
for (const auto &subs_dir : std::filesystem::directory_iterator(episode_sub_dir))
|
||||
{
|
||||
// only care about English (lol)
|
||||
std::string sub_filename = subs_dir.path().filename();
|
||||
if (sub_filename.ends_with("English.srt"))
|
||||
{
|
||||
// fix filename
|
||||
std::string sub_new_filename = episode_filename + "_" + sub_filename;
|
||||
|
||||
// move to season directory
|
||||
std::string new_sub_dir = top_seasons_dir + "/" + sub_new_filename;
|
||||
|
||||
try
|
||||
{
|
||||
std::filesystem::rename(subs_dir.path(), new_sub_dir);
|
||||
}
|
||||
catch (std::filesystem::filesystem_error &e)
|
||||
{
|
||||
std::cout << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//delete "Subs" directory
|
||||
try
|
||||
{
|
||||
std::filesystem::remove_all(seasons_dir_subs);
|
||||
}
|
||||
catch (std::filesystem::filesystem_error &e)
|
||||
{
|
||||
std::cout << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user