run_cmd.zip/run_cmd/main.cpp
#include <iostream>
#include <string>
#include <Windows.h>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <boost/program_options.hpp>
int proc(const boost::filesystem::path &path, const std::vector<std::string> &ext, const std::string &cmd, const bool isSilent, const bool isVerbose, const bool isRecursive) {
if (boost::filesystem::is_directory(path)) {
if (!isRecursive) {
return 0;
}
int result = 0;
for (const boost::filesystem::path &item : boost::filesystem::directory_iterator(path)) {
const int curResult = proc(item, ext, cmd, isSilent, isVerbose, isRecursive);
if (curResult != 0) {
result = curResult;
}
}
return result;
}
if (!ext.empty() && std::find(ext.begin(), ext.end(), path.extension()) == ext.end()) {
return 0;
}
const std::string target = path.string();
const std::string cmdline = (boost::format("%s %s") % cmd % target).str();
const int result = ::system(cmdline.c_str());
if (isVerbose) {
if (result == 0) {
std::cout << boost::format("success: %s\n") % target;
} else {
std::cout << boost::format("failure: %s\n") % target;
}
}
if (!isSilent && result != 0) {
std::cout << boost::format("failure: %s\n") % cmdline;
}
return result;
}
int main(const unsigned int argc, const char * const * argv) {
std::locale loc = std::locale("japanese").combine<std::numpunct<char> >(std::locale::classic()).combine<std::numpunct<wchar_t> >(std::locale::classic());
std::locale::global(loc);
std::wcout.imbue(loc);
std::cout.imbue(loc);
boost::program_options::variables_map opt_list;
try {
using boost::program_options::value;
boost::program_options::options_description opt("オプション");
opt.add_options()
("help,h", "ヘルプを表示")
("silent,s", "標準出力に出さない")
("verbose,v", "詳細表示")
("recursive,r", "サブディレクトリも対象にする")
("ext,e", value<std::vector<std::string> >(), "対象の拡張子")
("target,t", value<std::string>(), "対象のファイル/ディレクトリ")
("cmd,c", value<std::string>(), "実行するコマンド");
boost::program_options::positional_options_description pos;
pos.add("cmd", 1);
pos.add("target", 1);
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(opt).positional(pos).run(), opt_list);
boost::program_options::notify(opt_list);
if (opt_list.count("help") != 0 || opt_list.count("target") == 0 || opt_list.count("cmd") == 0) {
std::wcout << boost::wformat(L"usage: %s [OPTION] [--cmd] cmd [--target] path\n") % boost::filesystem::path(argv[0]).filename().wstring();
std::cout << opt << std::endl;
return 1;
}
} catch (std::exception& ex) {
std::cout << "コマンドライン引数の指定に誤りがあります: " << ex.what() << std::endl;
return 1;
}
const boost::filesystem::path target = opt_list["target"].as<std::string>();
const std::string cmd = opt_list["cmd"].as<std::string>();
const bool isSilent = (opt_list.count("silent") != 0);
const bool isVerbose = (opt_list.count("verbose") != 0);
const bool isRecursive = (opt_list.count("recursive") != 0);
const std::vector<std::string> ext = opt_list["ext"].as<std::vector<std::string> >();
if (boost::filesystem::is_regular_file(target)) {
return proc(target, ext, cmd, isSilent, isVerbose, isRecursive);
} else if (boost::filesystem::is_directory(target)) {
int result = 0;
for (const boost::filesystem::path &item : boost::filesystem::directory_iterator(target)) {
const int curResult = proc(item, ext, cmd, isSilent, isVerbose, isRecursive);
if (curResult != 0) {
result = curResult;
}
}
return result;
} else {
std::wcout << L"ファイルもしくはディレクトリを指定してください。\n";
return 1;
}
}