読者です 読者をやめる 読者になる 読者になる

YAMAGUCHI::weblog

土足で窓から失礼いたします。今日からあなたの息子になります。 当年とって92歳、下町の発明王、エジソンです。

ディレクトリの中身を再帰的に表示

最近はデータを大量に取得して、一気にバッチ処理に掛けるみたいなことをやってますが、いい加減シェルスクリプトを書くのがめんどくさくなってきたので、それ専用のクラスを作ってしまおうと昨日くらいから書き始めました。で、一応できたんでソースを載せてみます。こうした方がいいよ、という意見があれば是非コメントまで。

#include <sys/types.h>
#include <dirent.h>
#include <iostream>
using std::cerr;
using std::endl;

void show_files( const char* _cur, const char* _parent) {
    std::string path(_parent);
    if ( path.length() > 0 )
        path += "/";
    path += _cur;

    DIR* dp = opendir( path.c_str() );
    if ( dp == NULL ) {
         cerr << path << endl;
         return;
    }

    struct dirent* entp;
    while ( (entp = readdir(dp)) != NULL ) {
        std::string buff = path;
        
        if ( entp->d_name[0] != '.' )  // ドットで始まるディレクトリを回避
            dir_files( entp->d_name, buff.c_str() );
    }

    closedir(dp);
    return;
}

本当は sys/stat.h 内のstat()を使って

#include <sys/stat.h>
int is_dir (const struct dirent* _entp) {
    struct stat sb;
    stat(_entp->d_name, &sb);

    if ( S_ISDIR(sb.st_mode) )
        return 1;
    else if ( S_ISREG(sb.st_mode) )
        return 2;
    else
        return 0;
}

みたいな感じにしたかったんだけど、どうもカレントディレクトリ以外のディレクトリのファイルのモードはS_IFSOCKになってしまうみたいですね。そのおかげでだいぶはまってしまいました。コレを解消する方法はないかなぁ?
ちなみにcygwinLinuxBSDでdirent構造体の実装が違うみたいですね。dirent.d_type を使えば一発でディレクトリかどうかの判別ができたのに。

ここではd_typeは

Linux 以外では、 d_type フィールドは主に BSD 系のシステムでだけ存在する。

とあるんで、「cygwinもあるんじゃね?」と期待したけど、実際のcygwinの実装では

struct dirent
{
  long d_version;
  long d_reserved[2];
  long d_fd;
  ino_t d_ino;
  char d_name[256];
};

となってました。見事にありません。残念。