Abstract
The bash shell utility mkdir is a tool used to create directories in most POSIX environments. I thought it would be fun to implement such functionality from C++ and maybe forge in some of my own features in the future. I will be using the C++ library Boost to handle the command line options and the Standard Template Libary (std) to work work with the filesystem. I would appreciate some sustains, nays, and comments on the 50 so lines of code I have written.
Code
mkdir.cpp
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <filesystem>
#include <iostream>
#include <string.h>
#include <string>
#include <vector>
// Define the LOG() macro in order to be able to add
// a logger in the future without too much refactoring
//#define LOG(x) BOOST_LOG_TRIVIAL(x)
#define LOG(x) std::cout
int main(int argc, char **argv) {
// Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()
("help,h", "produce help message")
("parents,p", po::bool_switch(), "no error if existing, make parent directories as needed")
("verbose,v", po::bool_switch(), "print a message for each created directory");
const po::parsed_options parsed = po::command_line_parser(argc, argv)
.options(desc).allow_unregistered().run();
const std::vector<std::string> unrecognized =
collect_unrecognized(parsed.options, po::include_positional);
po::variables_map vm;
po::store(parsed, vm);
po::notify(vm);
for (const auto &opt : unrecognized) {
if (opt[0] == '-') {
LOG(error) << "Unknown option '" << opt << "'\n";
return 1;
}
}
if (vm.count("help") || argc <= 1) {
LOG(info) << desc;
return 1;
}
std::error_code ec;
for (const auto &dir_name : unrecognized) {
auto path = std::filesystem::absolute(std::filesystem::path(dir_name));
if (vm["parents"].as<bool>())
std::filesystem::create_directories(path, ec);
else
std::filesystem::create_directory(path, ec);
if (errno) {
LOG(error) << "Cannot create directory '" << dir_name
<< "': " << strerror(errno) << '\n';
errno = 0;
} else {
LOG(info) << "Created directory '" << dir_name << "'\n";
}
}
return 0;
}
Try it!
In order to compile this utility the following packages are needed:
sudo apt install build-essential libboost-program-options-dev
Then you can compile mkdir.cpp with:
g++ mkdir.cpp -o mkdir -lboost_program_options -std=c++2a
Then you can test it out with:
./mkdir <options> <directory names>
-moption is missing,mkdir -p foosucceeds even whenfoois a regular file,mkdir -p foo/barprints an error message but actually works,-lboost_optionsdoesn't work on Ubuntu (-lboost_program_optionsdoes), andlibboost-program-options-devtakes 145 MB of disk space. \$\endgroup\$libboost-program-options-devso it wasn't a runtime dependency, and other users of pre-built binaries would only pay for the disk space consumed by the components actually used? \$\endgroup\$/bin/mkdiris 88 kilobytes), but yeah, far better than having to install such a ridiculously large library for a program with such limited functionality. Thanks \$\endgroup\$