C++11
This commit is contained in:
parent
e5c02be1e0
commit
49a490061e
9
Makefile
9
Makefile
@ -1,13 +1,16 @@
|
||||
CC ?= clang
|
||||
CXX ?= clang++
|
||||
CFLAGS ?= -O2 -g -Wall -Wextra -std=c++17
|
||||
CFLAGS ?= -O2 -g -Wall -Wextra -std=c++11
|
||||
|
||||
default: tv_rename
|
||||
|
||||
# using libc++ because libstdc++ has a bug in regex that causes seg fault with long lines
|
||||
|
||||
tv_rename: functions.o tv_rename.cpp
|
||||
$(CXX) $(CFLAGS) -stdlib=libc++ -o tv_rename tv_rename.cpp functions.o -lcurl -lc++fs
|
||||
tv_rename: functions.o filesystem.o tv_rename.cpp
|
||||
$(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
|
||||
$(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 "filesystem.hpp"
|
||||
#include <iostream>
|
||||
#include <curl/curl.h>
|
||||
#include <stdlib.h>
|
||||
@ -34,34 +35,32 @@ std::string Curl::execute(const std::string &url) {
|
||||
return source;
|
||||
}
|
||||
|
||||
void findSeason(std::set<std::experimental::filesystem::path> &files, int season, const std::string &path) {
|
||||
namespace fs = std::experimental::filesystem;
|
||||
void findSeason(std::set<std::string> &files, int season, const std::string &path) {
|
||||
std::smatch match;
|
||||
auto episode = std::regex("[sS][0]{0,2000}" + std::to_string(season) + "[eE][0-9]{1,2000}");
|
||||
for( auto& p: fs::directory_iterator(path) ) {
|
||||
if(fs::is_directory(p)) {
|
||||
findSeason(files, season, p.path());
|
||||
for( const auto& p: FSLib::Directory(path) ) {
|
||||
if(FSLib::isDirectory(path + "/" + p)) {
|
||||
findSeason(files, season, path + "/" + p);
|
||||
continue;
|
||||
}
|
||||
std::string a = p.path().filename();
|
||||
if( std::regex_search(a, episode) ) {
|
||||
files.insert(p.path());
|
||||
|
||||
if( std::regex_search(p, episode) ) {
|
||||
files.insert(path + "/" + p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iterateFS(std::set<int> &seasons, const std::string &path) {
|
||||
namespace fs = std::experimental::filesystem;
|
||||
std::smatch match;
|
||||
auto episode = std::regex("[sS][0-9]{1,2000}[eE][0-9]{1,2000}");
|
||||
for( auto& p: fs::directory_iterator(path) ) {
|
||||
if(fs::is_directory(p)) {
|
||||
iterateFS(seasons, p.path());
|
||||
for( const auto& p: FSLib::Directory(path) ) {
|
||||
if(FSLib::isDirectory(path + "/" + p)) {
|
||||
iterateFS(seasons, path + "/" + p);
|
||||
continue;
|
||||
}
|
||||
std::string a = p.path().filename();
|
||||
if( std::regex_search(a, match, episode) ) {
|
||||
a = match[0];
|
||||
|
||||
if( std::regex_search(p, match, episode) ) {
|
||||
std::string a = match[0];
|
||||
a = std::regex_replace(a, std::regex("[eE][0-9]{1,2000}"), "");
|
||||
a = a.substr(1);
|
||||
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 ) {
|
||||
using namespace std::string_literals;
|
||||
auto search = std::regex_replace(show, std::regex(" "), "+");
|
||||
auto source_code = c.execute("https://www.thetvdb.com/search?q=" + search + "&l=" + language);
|
||||
auto series = std::regex("<td><a href=\"/series.*?</td>");
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <experimental/filesystem>
|
||||
#include <curl/curl.h>
|
||||
|
||||
class Curl {
|
||||
@ -16,7 +15,7 @@ private:
|
||||
};
|
||||
|
||||
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 printHelp();
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
#include "filesystem.hpp"
|
||||
|
||||
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 );
|
||||
@ -18,7 +18,6 @@ bool linux{false};
|
||||
Curl c;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
namespace fs = std::filesystem;
|
||||
std::map<std::string, std::string> languages{
|
||||
{"en", "English"}, {"sv", "Svenska"}, {"no", "Norsk"}, {"da", "Dansk"}, {"fi", "Suomeksi"},
|
||||
{"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])) ) {
|
||||
path = std::string(argv[x+1]);
|
||||
x++;
|
||||
if( !fs::exists(fs::absolute(path)) )
|
||||
if( !FSLib::isDirectory(path) )
|
||||
change_dir = true;
|
||||
} else if ( !(strcmp("-t", argv[x]) && strcmp("--trust", argv[x])) ) {
|
||||
trust = true;
|
||||
@ -73,13 +72,12 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
while( change_dir ) {
|
||||
auto abs = fs::absolute(path);
|
||||
if( !fs::exists(abs) ) {
|
||||
if( !FSLib::isDirectory(path) ) {
|
||||
std::cout << "This directory doesn't exist, please insert a correct path: " << std::endl;
|
||||
std::getline(std::cin, path);
|
||||
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::cin >> response;
|
||||
std::cin.ignore(1,'\n');
|
||||
@ -92,10 +90,8 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
path = fs::absolute(path);
|
||||
|
||||
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::string response;
|
||||
std::cin >> response;
|
||||
@ -155,16 +151,24 @@ void singleSeason( const std::string &path, const std::string &show, int season,
|
||||
}
|
||||
if( episodes.empty() )
|
||||
return;
|
||||
std::set<std::experimental::filesystem::path> files;
|
||||
std::set<std::experimental::filesystem::path> renamed_files;
|
||||
std::set<std::string> files;
|
||||
std::set<std::string> renamed_files;
|
||||
std::vector<std::string> renamed_episodes;
|
||||
renamed_episodes.resize(episodes.size());
|
||||
findSeason(files, season, path);
|
||||
if( files.empty() )
|
||||
return;
|
||||
for( const auto &x : files ) {
|
||||
std::string name = x.filename();
|
||||
std::string dir = x.parent_path();
|
||||
auto last = x.find_last_of("/");
|
||||
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;
|
||||
try {
|
||||
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();
|
||||
namespace fs = std::experimental::filesystem;
|
||||
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;
|
||||
}
|
||||
if( !trust ) {
|
||||
@ -200,9 +203,8 @@ void singleSeason( const std::string &path, const std::string &show, int season,
|
||||
return;
|
||||
}
|
||||
orig = files.begin();
|
||||
namespace fs = std::experimental::filesystem;
|
||||
for(auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed) {
|
||||
fs::rename(*orig, *renamed);
|
||||
FSLib::rename(*orig, *renamed);
|
||||
++orig;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user