C++11
This commit is contained in:
parent
e5c02be1e0
commit
49a490061e
9
Makefile
9
Makefile
@ -1,13 +1,16 @@
|
|||||||
CC ?= clang
|
CC ?= clang
|
||||||
CXX ?= clang++
|
CXX ?= clang++
|
||||||
CFLAGS ?= -O2 -g -Wall -Wextra -std=c++17
|
CFLAGS ?= -O2 -g -Wall -Wextra -std=c++11
|
||||||
|
|
||||||
default: tv_rename
|
default: tv_rename
|
||||||
|
|
||||||
# using libc++ because libstdc++ has a bug in regex that causes seg fault with long lines
|
# using libc++ because libstdc++ has a bug in regex that causes seg fault with long lines
|
||||||
|
|
||||||
tv_rename: functions.o tv_rename.cpp
|
tv_rename: functions.o filesystem.o tv_rename.cpp
|
||||||
$(CXX) $(CFLAGS) -stdlib=libc++ -o tv_rename tv_rename.cpp functions.o -lcurl -lc++fs
|
$(CXX) $(CFLAGS) -stdlib=libc++ -o tv_rename tv_rename.cpp functions.o filesystem.o -lcurl
|
||||||
|
|
||||||
|
filesystem.o: filesystem.cpp
|
||||||
|
$(CXX) $(CFLAGS) -stdlib=libc++ -c filesystem.cpp
|
||||||
|
|
||||||
functions.o: functions.cpp
|
functions.o: functions.cpp
|
||||||
$(CXX) $(CFLAGS) -stdlib=libc++ -c functions.cpp
|
$(CXX) $(CFLAGS) -stdlib=libc++ -c functions.cpp
|
||||||
|
29
filesystem.cpp
Normal file
29
filesystem.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "filesystem.hpp"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
|
||||||
|
bool FSLib::exists(const std::string &path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
return stat( path.c_str(), &path_stat ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSLib::isDirectory(const std::string &path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
stat( path.c_str(), &path_stat );
|
||||||
|
return S_ISDIR(path_stat.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FSLib::canonical(const std::string &path) {
|
||||||
|
char *canonical_path = static_cast<char *>(malloc(PATH_MAX));
|
||||||
|
if( realpath(path.c_str(), canonical_path) == nullptr )
|
||||||
|
return "";
|
||||||
|
std::string canonical_string{canonical_path};
|
||||||
|
free(canonical_path);
|
||||||
|
return canonical_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSLib::rename(const std::string &file_a, const std::string &file_b) {
|
||||||
|
return ::rename( file_a.c_str(), file_b.c_str() ) == 0;
|
||||||
|
}
|
||||||
|
|
106
filesystem.hpp
Normal file
106
filesystem.hpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#ifndef FSLIB_H
|
||||||
|
#define FSLIB_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace FSLib{
|
||||||
|
bool exists(const std::string &path);
|
||||||
|
bool isDirectory(const std::string &path);
|
||||||
|
std::string canonical(const std::string &path);
|
||||||
|
bool rename(const std::string &file_a, const std::string &file_b);
|
||||||
|
|
||||||
|
class Directory {
|
||||||
|
public:
|
||||||
|
Directory(const std::string &path_) : dir_path(path_) {}
|
||||||
|
Directory() = delete;
|
||||||
|
Directory(const Directory &d) = default;
|
||||||
|
Directory(Directory &&d) = default;
|
||||||
|
|
||||||
|
class Iterator {
|
||||||
|
public:
|
||||||
|
Iterator( const Directory &d_ ) : d(opendir(d_.path())) {
|
||||||
|
current_entry = readdir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator( const Directory &d_, const struct dirent *current_entry_) : d(opendir(d_.path())), current_entry(current_entry_) {}
|
||||||
|
|
||||||
|
Iterator() = delete;
|
||||||
|
|
||||||
|
Iterator(const Iterator &i) = default;
|
||||||
|
|
||||||
|
Iterator(Iterator &&i) = default;
|
||||||
|
|
||||||
|
~Iterator() {
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator*() {
|
||||||
|
return current_entry->d_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator &operator++() {
|
||||||
|
if( current_entry == nullptr )
|
||||||
|
return *this;
|
||||||
|
current_entry = readdir(d);
|
||||||
|
if( current_entry != nullptr && (!strcmp(current_entry->d_name, ".") || !strcmp(current_entry->d_name, "..")) )
|
||||||
|
operator++();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator++(int) {
|
||||||
|
Iterator ret(*this);
|
||||||
|
operator++();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Iterator &i_other) {
|
||||||
|
return i_other.current_entry == current_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator &i_other) {
|
||||||
|
return i_other.current_entry != current_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIR *d;
|
||||||
|
const struct dirent *current_entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
using iterator = Iterator;
|
||||||
|
using const_iterator = Iterator;
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return Iterator(dir_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return Iterator(dir_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return Iterator(dir_path, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return Iterator(dir_path, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const {
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *path() const {
|
||||||
|
return dir_path.c_str();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string dir_path;
|
||||||
|
};
|
||||||
|
} //end FSLib
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
#include "functions.hpp"
|
#include "functions.hpp"
|
||||||
|
#include "filesystem.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -34,34 +35,32 @@ std::string Curl::execute(const std::string &url) {
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void findSeason(std::set<std::experimental::filesystem::path> &files, int season, const std::string &path) {
|
void findSeason(std::set<std::string> &files, int season, const std::string &path) {
|
||||||
namespace fs = std::experimental::filesystem;
|
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
auto episode = std::regex("[sS][0]{0,2000}" + std::to_string(season) + "[eE][0-9]{1,2000}");
|
auto episode = std::regex("[sS][0]{0,2000}" + std::to_string(season) + "[eE][0-9]{1,2000}");
|
||||||
for( auto& p: fs::directory_iterator(path) ) {
|
for( const auto& p: FSLib::Directory(path) ) {
|
||||||
if(fs::is_directory(p)) {
|
if(FSLib::isDirectory(path + "/" + p)) {
|
||||||
findSeason(files, season, p.path());
|
findSeason(files, season, path + "/" + p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string a = p.path().filename();
|
|
||||||
if( std::regex_search(a, episode) ) {
|
if( std::regex_search(p, episode) ) {
|
||||||
files.insert(p.path());
|
files.insert(path + "/" + p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iterateFS(std::set<int> &seasons, const std::string &path) {
|
void iterateFS(std::set<int> &seasons, const std::string &path) {
|
||||||
namespace fs = std::experimental::filesystem;
|
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
auto episode = std::regex("[sS][0-9]{1,2000}[eE][0-9]{1,2000}");
|
auto episode = std::regex("[sS][0-9]{1,2000}[eE][0-9]{1,2000}");
|
||||||
for( auto& p: fs::directory_iterator(path) ) {
|
for( const auto& p: FSLib::Directory(path) ) {
|
||||||
if(fs::is_directory(p)) {
|
if(FSLib::isDirectory(path + "/" + p)) {
|
||||||
iterateFS(seasons, p.path());
|
iterateFS(seasons, path + "/" + p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string a = p.path().filename();
|
|
||||||
if( std::regex_search(a, match, episode) ) {
|
if( std::regex_search(p, match, episode) ) {
|
||||||
a = match[0];
|
std::string a = match[0];
|
||||||
a = std::regex_replace(a, std::regex("[eE][0-9]{1,2000}"), "");
|
a = std::regex_replace(a, std::regex("[eE][0-9]{1,2000}"), "");
|
||||||
a = a.substr(1);
|
a = a.substr(1);
|
||||||
seasons.insert(std::stoi(a));
|
seasons.insert(std::stoi(a));
|
||||||
@ -70,7 +69,6 @@ void iterateFS(std::set<int> &seasons, const std::string &path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string getDefUrl( const std::string &show, const std::string &language, Curl &c ) {
|
std::string getDefUrl( const std::string &show, const std::string &language, Curl &c ) {
|
||||||
using namespace std::string_literals;
|
|
||||||
auto search = std::regex_replace(show, std::regex(" "), "+");
|
auto search = std::regex_replace(show, std::regex(" "), "+");
|
||||||
auto source_code = c.execute("https://www.thetvdb.com/search?q=" + search + "&l=" + language);
|
auto source_code = c.execute("https://www.thetvdb.com/search?q=" + search + "&l=" + language);
|
||||||
auto series = std::regex("<td><a href=\"/series.*?</td>");
|
auto series = std::regex("<td><a href=\"/series.*?</td>");
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <experimental/filesystem>
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
class Curl {
|
class Curl {
|
||||||
@ -16,7 +15,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string getDefUrl( const std::string &show, const std::string &language, Curl &c );
|
std::string getDefUrl( const std::string &show, const std::string &language, Curl &c );
|
||||||
void findSeason(std::set<std::experimental::filesystem::path> &files, int season, const std::string &path);
|
void findSeason(std::set<std::string> &files, int season, const std::string &path);
|
||||||
void iterateFS(std::set<int> &seasons, const std::string &path);
|
void iterateFS(std::set<int> &seasons, const std::string &path);
|
||||||
void printHelp();
|
void printHelp();
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <filesystem>
|
#include "filesystem.hpp"
|
||||||
|
|
||||||
void singleSeason( const std::string &path, const std::string &show, int season, std::string url );
|
void singleSeason( const std::string &path, const std::string &show, int season, std::string url );
|
||||||
void multipleSeasons( const std::string &path, const std::string &show, const std::set<int> seasons );
|
void multipleSeasons( const std::string &path, const std::string &show, const std::set<int> seasons );
|
||||||
@ -18,7 +18,6 @@ bool linux{false};
|
|||||||
Curl c;
|
Curl c;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
namespace fs = std::filesystem;
|
|
||||||
std::map<std::string, std::string> languages{
|
std::map<std::string, std::string> languages{
|
||||||
{"en", "English"}, {"sv", "Svenska"}, {"no", "Norsk"}, {"da", "Dansk"}, {"fi", "Suomeksi"},
|
{"en", "English"}, {"sv", "Svenska"}, {"no", "Norsk"}, {"da", "Dansk"}, {"fi", "Suomeksi"},
|
||||||
{"nl", "Nederlands"}, {"de", "Deutsch"}, {"it", "Italiano"}, {"es", "Español"}, {"fr", "Français"},
|
{"nl", "Nederlands"}, {"de", "Deutsch"}, {"it", "Italiano"}, {"es", "Español"}, {"fr", "Français"},
|
||||||
@ -46,7 +45,7 @@ int main(int argc, char** argv) {
|
|||||||
} else if ( !(strcmp("-sp", argv[x]) && strcmp("--show-path", argv[x])) ) {
|
} else if ( !(strcmp("-sp", argv[x]) && strcmp("--show-path", argv[x])) ) {
|
||||||
path = std::string(argv[x+1]);
|
path = std::string(argv[x+1]);
|
||||||
x++;
|
x++;
|
||||||
if( !fs::exists(fs::absolute(path)) )
|
if( !FSLib::isDirectory(path) )
|
||||||
change_dir = true;
|
change_dir = true;
|
||||||
} else if ( !(strcmp("-t", argv[x]) && strcmp("--trust", argv[x])) ) {
|
} else if ( !(strcmp("-t", argv[x]) && strcmp("--trust", argv[x])) ) {
|
||||||
trust = true;
|
trust = true;
|
||||||
@ -73,13 +72,12 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while( change_dir ) {
|
while( change_dir ) {
|
||||||
auto abs = fs::absolute(path);
|
if( !FSLib::isDirectory(path) ) {
|
||||||
if( !fs::exists(abs) ) {
|
|
||||||
std::cout << "This directory doesn't exist, please insert a correct path: " << std::endl;
|
std::cout << "This directory doesn't exist, please insert a correct path: " << std::endl;
|
||||||
std::getline(std::cin, path);
|
std::getline(std::cin, path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::cout << "Is this the right directory? " << fs::canonical(abs) << std::endl;
|
std::cout << "Is this the right directory? " << FSLib::canonical(path) << std::endl;
|
||||||
std::string response;
|
std::string response;
|
||||||
std::cin >> response;
|
std::cin >> response;
|
||||||
std::cin.ignore(1,'\n');
|
std::cin.ignore(1,'\n');
|
||||||
@ -92,10 +90,8 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
path = fs::absolute(path);
|
|
||||||
|
|
||||||
if( show.empty() ) {
|
if( show.empty() ) {
|
||||||
show = std::regex_replace(fs::canonical(path).c_str(), std::regex(".*/"), "");
|
show = std::regex_replace(FSLib::canonical(path).c_str(), std::regex(".*/"), "");
|
||||||
std::cout << "Is this the right show name? " << show << std::endl;
|
std::cout << "Is this the right show name? " << show << std::endl;
|
||||||
std::string response;
|
std::string response;
|
||||||
std::cin >> response;
|
std::cin >> response;
|
||||||
@ -155,16 +151,24 @@ void singleSeason( const std::string &path, const std::string &show, int season,
|
|||||||
}
|
}
|
||||||
if( episodes.empty() )
|
if( episodes.empty() )
|
||||||
return;
|
return;
|
||||||
std::set<std::experimental::filesystem::path> files;
|
std::set<std::string> files;
|
||||||
std::set<std::experimental::filesystem::path> renamed_files;
|
std::set<std::string> renamed_files;
|
||||||
std::vector<std::string> renamed_episodes;
|
std::vector<std::string> renamed_episodes;
|
||||||
renamed_episodes.resize(episodes.size());
|
renamed_episodes.resize(episodes.size());
|
||||||
findSeason(files, season, path);
|
findSeason(files, season, path);
|
||||||
if( files.empty() )
|
if( files.empty() )
|
||||||
return;
|
return;
|
||||||
for( const auto &x : files ) {
|
for( const auto &x : files ) {
|
||||||
std::string name = x.filename();
|
auto last = x.find_last_of("/");
|
||||||
std::string dir = x.parent_path();
|
std::string name;
|
||||||
|
std::string dir;
|
||||||
|
if( last == static_cast<size_t>(-1) ) {
|
||||||
|
name = x;
|
||||||
|
dir = ".";
|
||||||
|
} else {
|
||||||
|
name = x.substr(last+1);
|
||||||
|
dir = x.substr(0, last);
|
||||||
|
}
|
||||||
unsigned long num;
|
unsigned long num;
|
||||||
try {
|
try {
|
||||||
num = std::stoi(std::regex_replace(name, std::regex(".*[sS][0]{0,2000}" + std::to_string(season) + "[eE]([0-9]{1,2000}).*"), "$1"));
|
num = std::stoi(std::regex_replace(name, std::regex(".*[sS][0]{0,2000}" + std::to_string(season) + "[eE]([0-9]{1,2000}).*"), "$1"));
|
||||||
@ -185,9 +189,8 @@ void singleSeason( const std::string &path, const std::string &show, int season,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto orig = files.begin();
|
auto orig = files.begin();
|
||||||
namespace fs = std::experimental::filesystem;
|
|
||||||
for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) {
|
for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) {
|
||||||
std::cout << std::string((*orig).filename()) << " -> " << std::string((*renamed).filename()) << std::endl;
|
std::cout << *orig << " -> " << *renamed << std::endl;
|
||||||
++orig;
|
++orig;
|
||||||
}
|
}
|
||||||
if( !trust ) {
|
if( !trust ) {
|
||||||
@ -200,9 +203,8 @@ void singleSeason( const std::string &path, const std::string &show, int season,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
orig = files.begin();
|
orig = files.begin();
|
||||||
namespace fs = std::experimental::filesystem;
|
|
||||||
for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) {
|
for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) {
|
||||||
fs::rename(*orig, *renamed);
|
FSLib::rename(*orig, *renamed);
|
||||||
++orig;
|
++orig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user