Sunday, May 29, 2016

Tree command with boost::filesystem

The tree command is pretty handy to get an overview of the contents of small folders. By small I mean both in the number of files, and the number of levels in the directory structure.  A sample output of the tree command is as follows:

user@host:~/projects$ tree templates/
--CMakeLists.txt~
--app.s
--src
    |--CMakeLists.txt~
    |--#Templates.cpp#
    |--Templates.cpp
    |--Templates.cpp~
    |--CMakeLists.txt
--build
    |--Makefile
    |--CTestTestfile.cmake
    |--CMakeCache.txt
    |--src


Using boost::filesystem this can be achieved with a handful of lines, and your code is multi-platform without any extra effort:

#include <boost/filesystem.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/algorithm/replace.hpp>

#include <iostream>
#include <string>

namespace fs = boost::filesystem;

void print(const fs::path& p,
           std::ostream& os = std::cout,
           const std::string& preffix = "--") {
  try {
    fs::directory_iterator it{p};
    while (it != fs::directory_iterator{}) {
      auto filename = it->path().filename().string();
      boost::replace_all(filename, "\"", "");
      std::cout << preffix << filename << std::endl;

      if(fs::is_directory(it->status())) {
        auto pfx = std::string("    |") + preffix;
        print(it->path(), os, pfx);
      }
      ++it;
    }
  } catch(const fs::filesystem_error& err) {
    std::cout << preffix << err.what() << std::endl;
  }
}

int main(int argc, char** argv) {
  if(argc > 1)
    print(argv[1]);
  else
    print(fs::current_path());
}

Happy Coding.