ディレクトリを走査する必要が出たので Boost.Filesystem を利用する事にしました.Boost のビルドを行っていなかったので,ビルドから始めてサンプルプログラムを実行するまでのメモ.
Boost のビルド
ビルドは以下の 2 コマンドで終了します.
[boost_1_40_0]$ ./bootstrap.sh --prefix=/usr [boost_1_40_0]$ ./bjam install
昔,Boost のビルドにもの凄く苦労した記憶があるのですが,随分と簡単になっているようです.bootstrap.bat と言うファイルが見えるので,Windows でも同様の方法でビルドできるのではないのかなと思います.
サンプルプログラム
手抜き ls.
#include <iostream> #include <boost/filesystem.hpp> int main(int argc, char* argv[]) { boost::filesystem::path dir = (argc <= 1) ? boost::filesystem::current_path() : boost::filesystem::path(argv[1]); // 絶対パスに変換する. std::cout << boost::filesystem::complete(dir).string() << std::endl; std::cout << std::endl; boost::filesystem::directory_iterator pos(dir); boost::filesystem::directory_iterator last; for (; pos != last; ++pos) { boost::filesystem::path p(*pos); if (boost::filesystem::is_directory(p)) { std::cout << p.leaf() << "/" << std::endl; } else std::cout << p.leaf() << std::endl; } return 0; }
実行結果
必要なライブラリは,以下の 2 つのようです.
- libboost_filesystem
- libboost_system
[example]$ g++ -Wall ex_boost_filesystem.cpp -lboost_filesystem -lboost_system [example]$ ./a c:/ c:/ $Recycle.Bin/ 4e2f5954c6a8a4c049484d5a63b9c8/ 99ee436e7432b337ad83/ b6d05b9d3141987ef6051fd0fe0cf6/ bin/ Boot/ bootmgr BOOTSECT.BAK code/ ...
その他
boost::filesystem::fstream
引数に boost::filesystem::path を指定する事ができる,std::fstream(のラッパクラス)だそうです.
directory_iterator
ディレクトリを走査するイテレータには下記の 2 種類が存在するようです.
directory_iterator は現在の階層のみを走査し,recursive_directory_iterator はある要素がディレクトリだった場合にその中身も走査の対象とするイテレータです.recursive_directory_iterator は深さ優先探索で指定されたディレクトリ以下全てのファイルを走査します.
recursive_directory_iterator には,no_push() と pop() と言うメソッドが用意されています.イテレータが指しているものがディレクトリの場合に no_push() を呼ぶと,そのディレクトリ以下のファイルは走査対象に含めなくなります.また,pop() を呼ぶと現在のディレクトリから抜けるようです.
path の各メソッドが返す文字列
boost::filesystem::path クラスには,root_path(), leaf() などのパスの一部分を返すメソッドが数多く用意されているので,それらのメソッドがどんな文字列を返すのかを調べてみました(実行結果は,Windows + cygwin での例).
[example]$ ./a ex_boost_filesystem2.cpp C:/code/cpp/example/ex_boost_filesystem2.cpp ----- root_path : C:/ root_name : C: root_directory : / relative_path : code/cpp/example/ex_boost_filesystem2.cpp leaf : ex_boost_filesystem2.cpp branch_path : C:/code/cpp/example string : C:/code/cpp/example/ex_boost_filesystem2.cpp file_string : C:\code\cpp\example\ex_boost_filesystem2.cpp directory_string: C:\code\cpp\example\ex_boost_filesystem2.cpp
使用したプログラムは,下記の通りです.
#include <iostream> #include <boost/filesystem.hpp> int main(int argc, char* argv[]) { boost::filesystem::path tmp = (argc <= 1) ? boost::filesystem::current_path() : boost::filesystem::path(argv[1]); boost::filesystem::path p = boost::filesystem::complete(tmp); std::cout << p.string() << std::endl; std::cout << "-----" << std::endl; std::cout << "root_path : " << p.root_path().string() << std::endl; std::cout << "root_name : " << p.root_name() << std::endl; std::cout << "root_directory : " << p.root_directory() << std::endl; std::cout << "relative_path : " << p.relative_path().string() << std::endl; std::cout << "leaf : " << p.leaf() << std::endl; std::cout << "branch_path : " << p.branch_path().string() << std::endl; std::cout << std::endl; std::cout << "string : " << p.string() << std::endl; std::cout << "file_string : " << p.file_string() << std::endl; std::cout << "directory_string: " << p.directory_string() << std::endl; return 0; }