stroll(nicer walk)のC++バージョンを書いた

ディレクトリを幅優先探索で掘っていき、ディレクトリやファイルに対する条件を適用し、それらを与えた条件(関数)によってソートし、見つけたファイルパスを返すライブラリを書いた。ちょうどPythonのos.walkを高機能にしたもので、所望のファイルだけを取り出したいときに使える。

boost不要で、C++11/C++14も不要なので、古いバージョンのg++(clang)でもコンパイルできる(はず)。Cでファイル処理を書くことはほとんど無いはずなので、C++で使えれば良いかなと。CとC++がごっちゃになっていてなんとなく居心地が悪いけどこんなもんなのだろうか。ちなみに、directory_iterator#incude <filesystem>が必要でMac(clang)だとコンパイルできないようなので、Cを使うことにした。

正規表現マッチをする際に、matchとsearchの違いを忘れてしまいがち。matchは先頭からマッチするが、searchはどこでもマッチする。

gist.github.com

$ cat main.cpp
#include <iostream>
#include "stroll.cpp"

using namespace std;
using namespace stroll;

void ex1(){
    cout<<"=== ex1 (mtime) ==="<<endl;
    Stroll stroll = Stroll("basedir");
    stroll.set_sortby(sortByMtime);

    while(stroll.read()){
        cout<< stroll.get() << endl;
    }
}

void ex2(){
    cout<<"=== ex2 (mtime/reverse) ==="<<endl;
    Stroll stroll = Stroll("basedir");
    stroll.set_sortby(sortByMtimeDesc);

    while(stroll.read()){
        cout<< stroll.get() << endl;
    }
}

void ex3(){
    cout<<"=== ex3 (no_file) ==="<<endl;
    vstr no_file;
    no_file.push_back("1$");
    no_file.push_back("2$");

    Stroll stroll = Stroll("basedir");
    stroll.set_no_file(no_file);

    while(stroll.read()){
        cout<< stroll.get() << endl;
    }
}

void ex4(){
    cout<<"=== ex4 (yes_path) ==="<<endl;
    vstr yes_path;
    yes_path.push_back("1$");

    Stroll stroll = Stroll("basedir");
    stroll.set_yes_path(yes_path);

    while(stroll.read()){
        cout<< stroll.get() << endl;
    }
}

void ex5(){
    cout<<"=== ex5 (no_root/len/reverse) ==="<<endl;
    vstr no_root;
    no_root.push_back("2$");

    Stroll stroll = Stroll("basedir");
    stroll.set_no_root(no_root);
    stroll.set_sortby(sortByLenDesc);

    while(stroll.read()){
        cout<< stroll.get() << endl;
    }
}

void ex6(){
    cout<<"=== ex6 (yes_file/yes_root) ==="<<endl;
    vstr yes_file;
    yes_file.push_back("2$");

    vstr yes_root;
    yes_root.push_back("2$");

    Stroll stroll = Stroll("basedir");
    stroll.set_yes_file(yes_file);
    stroll.set_yes_root(yes_root);

    while(stroll.read()){
        cout<< stroll.get() << endl;
    }
}

int main(int argc, char* argv[]){

    ex1();
    ex2();
    ex3();
    ex4();
    ex5();
    ex6();

    return 0;
}
$ cat Makefile 

main:main.o
    g++ -L./ -lstroll -o main main.o

main.o:libstroll.a
    g++ -c main.cpp

libstroll.a:stroll.o
    ar r libstroll.a stroll.o

stroll.o:stroll.cpp
    g++ -Wall -O2 -c stroll.cpp

.PHONY: clean
clean:
    rm -f libstroll.a stroll.o main
$ ./main 
=== ex1 (mtime) ===
basedir/file0
basedir/dir1/file11
basedir/dir1/file12
basedir/dir1/file13
basedir/dir1/file111
basedir/dir1/file1111
basedir/dir2/file21
basedir/dir2/file22
basedir/dir2/file23
basedir/dir2/file222
basedir/dir2/file2222
basedir/dir3/file31
basedir/dir3/file32
basedir/dir3/file33
basedir/dir3/file333
basedir/dir3/file3333
=== ex2 (mtime/reverse) ===
basedir/file0
basedir/dir3/file3333
basedir/dir3/file333
basedir/dir3/file33
basedir/dir3/file32
basedir/dir3/file31
basedir/dir2/file2222
basedir/dir2/file222
basedir/dir2/file23
basedir/dir2/file21
basedir/dir2/file22
basedir/dir1/file1111
basedir/dir1/file111
basedir/dir1/file13
basedir/dir1/file12
basedir/dir1/file11
=== ex3 (no_file) ===
basedir/file0
basedir/dir1/file13
basedir/dir2/file23
basedir/dir3/file33
basedir/dir3/file333
basedir/dir3/file3333
=== ex4 (yes_path) ===
basedir/file0
basedir/dir1/file11
basedir/dir1/file111
basedir/dir1/file1111
basedir/dir1/file12
basedir/dir1/file13
=== ex5 (no_root/len/reverse) ===
basedir/file0
basedir/dir1/file1111
basedir/dir1/file111
basedir/dir1/file11
basedir/dir1/file12
basedir/dir1/file13
basedir/dir3/file3333
basedir/dir3/file333
basedir/dir3/file31
basedir/dir3/file32
basedir/dir3/file33
=== ex6 (yes_file/yes_root) ===
basedir/dir2/file22
basedir/dir2/file222
basedir/dir2/file2222