bulkrename

Bulk file/directory renaming utility, similar to rangers built-in bulkrename command
git clone git://git.deurzen.net/bulkrename
Log | Files | Refs | LICENSE

commit 8de602ae3a34716e874ce334d0609a80536c9dbb
parent 9292bf9424c54f690f3a13fa159bb2b3293e31d8
Author: deurzen <m.deurzen@tum.de>
Date:   Wed,  4 Dec 2019 19:44:10 +0100

adds option to not recurse

Diffstat:
Msrc/bulkrename.cc | 4++--
Msrc/bulkrename.hh | 12+++++++++---
Msrc/main.cc | 2+-
Msrc/node.cc | 15++++++++++-----
Msrc/node.hh | 7++++---
Asrc/parse.cc | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/parse.hh | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/util.cc | 18++++++++++++++++++
Asrc/util.hh | 10++++++++++
9 files changed, 196 insertions(+), 14 deletions(-)

diff --git a/src/bulkrename.cc b/src/bulkrename.cc @@ -4,9 +4,9 @@ #include <iostream> ::std::unique_ptr<bulkrename_t> -bulkrename_t::init(const ::std::string& dir) +bulkrename_t::init(int argc, char** argv) { - return ::std::make_unique<bulkrename_t>(dir); + return ::std::make_unique<bulkrename_t>(argc, argv); } void diff --git a/src/bulkrename.hh b/src/bulkrename.hh @@ -1,6 +1,7 @@ #ifndef __BULKRENAME_BULKRENAME_GUARD__ #define __BULKRENAME_BULKRENAME_GUARD__ +#include "parse.hh" #include "node.hh" #include "file.hh" @@ -12,16 +13,21 @@ class bulkrename_t { public: - explicit bulkrename_t(const ::std::string& dir) - : dir_it(dir), tree(dir) + explicit bulkrename_t(int argc, char** argv) + : m_parser(argc, argv), + m_dir(m_parser.getargs().first ? m_parser.getargs().second[0] : "."), + dir_it(m_dir), + tree(!(m_parser.isset("n") || m_parser.isset("no-recurse")), m_dir) {} void setup(); void run(); - static ::std::unique_ptr<bulkrename_t> init(const ::std::string&); + static ::std::unique_ptr<bulkrename_t> init(int argc, char** argv); private: + parser_t m_parser; + ::std::string m_dir; ::std::filesystem::directory_iterator dir_it; nodetree_t tree; filehandler_t filehandler; diff --git a/src/main.cc b/src/main.cc @@ -7,7 +7,7 @@ int main(int argc, char** argv) { - auto brn = bulkrename_t::init(argc > 1 ? argv[1] : "."); + auto brn = bulkrename_t::init(argc, argv); brn->setup(); brn->run(); diff --git a/src/node.cc b/src/node.cc @@ -1,13 +1,18 @@ #include "node.hh" void -dir_t::populate(::std::filesystem::directory_iterator dir_it) +dir_t::populate(::std::filesystem::directory_iterator dir_it, bool recurse) { for (auto& entry : dir_it) { if (::std::filesystem::is_directory(entry)) { - dir_ptr_t dir = new dir_t(entry.path(), parent); - children.push_back(dir); - dir->populate(::std::filesystem::directory_iterator(entry)); + if (recurse) { + dir_ptr_t dir = new dir_t(entry.path(), parent); + children.push_back(dir); + dir->populate(::std::filesystem::directory_iterator(entry), recurse); + } else { + file_ptr_t file = new file_t(entry.path(), parent); + children.push_back(file); + } } else if (::std::filesystem::is_regular_file(entry)) { file_ptr_t file = new file_t(entry.path(), parent); children.push_back(file); @@ -19,7 +24,7 @@ dir_t::populate(::std::filesystem::directory_iterator dir_it) void nodetree_t::populate(::std::filesystem::directory_iterator dir_it) { - root->populate(dir_it); + root->populate(dir_it, recurse); } void diff --git a/src/node.hh b/src/node.hh @@ -70,7 +70,7 @@ public: : node_t(nodetype_t::dir, parent, path) {} - void populate(::std::filesystem::directory_iterator); + void populate(::std::filesystem::directory_iterator, bool recurse = false); bool has_next() const override { return !children.empty(); } void print(::std::ostream& out) const override; @@ -87,8 +87,8 @@ private: class nodetree_t { public: - explicit nodetree_t(const ::std::string& _root_name) - : root_name(_root_name), root(new dir_t(_root_name, nullptr)) + explicit nodetree_t(bool recurse, const ::std::string& _root_name) + : recurse(recurse), root_name(_root_name), root(new dir_t(_root_name, nullptr)) {} nodetree_t& operator=(const nodetree_t&) = delete; @@ -100,6 +100,7 @@ public: ::std::vector<file_ptr_t> get_files() const; private: + bool recurse; ::std::string root_name; dir_ptr_t root; diff --git a/src/parse.cc b/src/parse.cc @@ -0,0 +1,63 @@ +#include "parse.hh" +#include "util.hh" + + +void +parser_t::parse() +{ + for (size_t i = 0; i < m_opts.size(); ++i) { + if (m_opts[i].rfind("--", 0) != ::std::string::npos) { + ::std::string optflag = m_opts[i].substr(2); + if (!m_optmap.count(optflag)) continue; + option_t opt = m_optmap[optflag]; + if (opt.has_value && i+1 < m_opts.size()) { + setopt(optflag, m_opts[i+1]); + ++i; + } else if (!opt.flag.empty() && !opt.has_value) + setopt(optflag); + } else if (m_opts[i].rfind("-", 0) != ::std::string::npos) { + ::std::string optflags = m_opts[i].substr(1); + for (auto& optflag : optflags) + setopt(::std::string(1, optflag)); + } else if (i) { + m_args.push_back(m_opts[i]); + } + } +} + +void +parser_t::setopt(::std::string flag, ::std::string value) +{ + for (auto& opt : m_optlist) + if (!opt.flag.compare(flag)) { + opt.set = true; + opt.value = value; + } +} + +bool +parser_t::isset(::std::string flag) +{ + for (auto& opt : m_optlist) + if (!opt.flag.compare(flag)) { + return opt.set; + } + + return false; +} + +::std::pair<int, ::std::vector<char*>> +parser_t::getargs() +{ + ::std::vector<char*> raw; + for (auto& s : m_args) + raw.push_back(convert_new(s)); + + return {raw.size(), raw}; +} + +::std::vector<option_t> +parser_t::getopts() +{ + return m_optlist; +} diff --git a/src/parse.hh b/src/parse.hh @@ -0,0 +1,79 @@ +#ifndef __BULKRENAME__PARSE__GUARD__ +#define __BULKRENAME__PARSE__GUARD__ + +#include <string> +#include <vector> +#include <unordered_map> +#include <algorithm> +#include <iostream> + +enum option_type_t { longopt, shortopt }; + +struct option_t +{ + option_t() = default; + + option_t(option_type_t _type) + : type(_type), + has_value(false), + set(false) + {} + + option_t(option_type_t _type, ::std::string _flag, + ::std::string _desc, bool _has_value = false) + : flag(_flag), + desc(_desc), + has_value(_has_value), + set(false) + {} + + option_type_t type = shortopt; + ::std::string flag; + ::std::string desc; + ::std::string value; + bool has_value, set; +}; + + +class parser_t +{ +public: + parser_t(int argc, char** argv) + : m_opts(argv, argv + argc), + m_optlist({ + // short options flag description + { option_type_t::shortopt, "n", "do not recurse into directories" }, + + // long options flag description has value + { option_type_t::longopt, "no-recurse", "do not recurse into directories", false }, + }) + { + for (auto& opt : m_optlist) + m_optmap[opt.flag] = opt; + + ::std::vector<::std::string>::iterator it; + if ((it = ::std::find(m_opts.begin(), m_opts.end(), "--")) != m_opts.end()) { + ::std::move(it + 1, m_opts.end(), ::std::back_inserter(m_args)); + m_opts.erase(it, m_opts.end()); + } + + parse(); + } + + void parse(); + void setopt(::std::string, ::std::string = ""); + bool isset(::std::string); + + ::std::pair<int, ::std::vector<char*>> getargs(); + ::std::vector<option_t> getopts(); + +private: + ::std::vector<::std::string> m_opts; + ::std::vector<::std::string> m_args; + + ::std::vector<option_t> m_optlist; + ::std::unordered_map<::std::string, option_t> m_optmap; + +}; + +#endif//__BULKRENAME__PARSE__GUARD__ diff --git a/src/util.cc b/src/util.cc @@ -0,0 +1,18 @@ +#include "util.hh" + +#include <vector> +#include <string> + +char* +convert_new(const ::std::string& s) +{ + char* raw = new char[s.size() + 1]; + ::std::strcpy(raw, s.c_str()); + return raw; +} + +const char* +convert(const ::std::string& s) +{ + return s.c_str(); +} diff --git a/src/util.hh b/src/util.hh @@ -0,0 +1,10 @@ +#ifndef __BULKRENAME__UTIL__GUARD__ +#define __BULKRENAME__UTIL__GUARD__ + +#include <cstring> +#include <string> + +char* convert_new(const ::std::string&); +const char* convert(const ::std::string&); + +#endif//__BULKRENAME__UTIL__GUARD__