Directory

このプログラムはlsコマンドを真似たものです.
このプログラムの流れ.
argvの引数で渡されたオプションを読む.(ない場合は./dir -l .)

"-h", でヘルプ, "-l"で第3引数(ディレクトリ)の読み込み, それ以外はhelp("-h")を表示.
static void do_ls(const char *path)
"chdir"でパス指定されたディレクトリに移動. "getcwd"でbuff[32]にパス名を格納.

"opendir"でパスを開く. "readdir"で"struct dirent *read"にディレクトリの情報を取得でパス指定されたディレクトリに移動. "getcwd"でbuff[32]にパス名を格納.

"opendir"でパスを開く. "readdir"で"struct dirent *read"にディレクトリの情報を取得.

表示させる時間を人にわかりやすくするために"localtile"を用いる.

"stat"で取得したファイル名から詳細情報を取得.

"unistd"で定義されているマクロを用いて, ディレクトリか普通のファイルなのかを判断させる.

ファイルサイズを1K(1024)で割った値を"%6s"に入れる.

この時, ファイルサイズが1K以下ならそのままの値を返し, 1Kを越す場合は小数点以下切り捨てでKをつけて表示させる.

"exit" 正常値でプログラムを終了させる.

#include<stdio.h> /* printf */
#include<stdlib.h> /* exit */
#include<sys/types.h>
#include<sys/stat.h> /* stat */
#include<dirent.h> /* readdir, opendir */
#include<fcntl.h>
#include<unistd.h>
#include<time.h> /* ctime */

static void do_help(const char *path);
static void do_ls(const char *path);
char *return_size(const long int n, char *buff);

int main(int argc, char **argv)
{
    int opt;

    if(argc < 2) {
        argv[1] = "-l";
        argv[2] = ".";
        argc = 3;
    }

    if(argc > 3) {
        fprintf(stderr, "引数オーバー\n");
        exit(1);
    }

    while((opt = getopt(argc, argv, "hla:")) != EOF) {
        switch(opt) {
            case 'h':
                do_help(argv[0]);
                break;

            case 'l':
                if(argc != 3)
                    do_help(argv[0]);
                do_ls(argv[2]);
                break;

            case '?':
                do_help(argv[0]);
                break;
        }
    }

    printf("無効な引数\n");

    return 0;
}

static void do_help(const char *path) {
    printf("第3引数で指定されたディレクトリの内部表示\n");
    printf("usage: %s [-option] Directory name\n", path);
    printf("\t-h ヘルプ\n");
    printf("\t-l 詳細表示\n");
    exit(0);
}

static void do_ls(const char *path) {
    struct dirent *read; /* readdir */
    struct tm *time; /* localtime */
    struct stat ls; /* stat */
    char buff[BUFSIZ]; /* パスの取得 */
    char size_buff[BUFSIZ]; /* サイズの表示 */
    DIR *opd;
    char *week[512] = {"日", "月", "火", "水", "木", "金", "土"};

    if(chdir(path) == EOF) {
        perror("chdir");
        exit(1);
    }

    if(getcwd(buff, BUFSIZ) == NULL) {
        perror("getcwd");
        exit(1);
    }

    if((opd = opendir(buff)) == NULL) {
            perror("opendir");
            exit(1);
    }

    while((read = readdir(opd)) != NULL) {
        if((time = localtime(&ls.st_ctime)) == NULL) {
            perror("localtime");
            closedir(opd);
            exit(1);
        }

        if(stat(read->d_name, &ls) == EOF)
            printf("無意味なディレクトリ:%s\n", read->d_name);

        if(S_ISREG(ls.st_mode)) {
            printf("       %4o %18s %6s %3d %4d年%2d月%2d日(%s) %2d時%02d分%02d秒\n",
                    (ls.st_mode & ~S_IFMT), /* 許可 */
                    read->d_name,  /* ファイル名 */
                    return_size(ls.st_size, size_buff), /* ファイルサイズ */
                    ls.st_nlink, /* リンク数 */
                    time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, /* 年 月 日 */
                    week[time->tm_wday], time->tm_hour, time->tm_min, /* 曜日 時間 分 */
                    time->tm_sec); /* 秒 */
        }
        if(S_ISDIR(ls.st_mode)) {
            printf(" <DIR> %4o %18s %6s %3d %4d年%2d月%2d日(%s) %2d時%02d分%02d秒\n",
                    (ls.st_mode & ~S_IFMT), /* 許可 */
                    read->d_name, /* ファイル名 */
                    return_size(ls.st_size, size_buff), /* ファイルサイズ */
                    ls.st_nlink, /* リンク数 */
                    time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, /* 年 月 日 */
                    week[time->tm_wday], time->tm_hour, time->tm_min, /* 曜日 時間 分 */
                    time->tm_sec); /* 秒 */
       }
    }

    closedir(opd);
    exit(0);
}

char *return_size(const long int n, char *buff) {
    int result = (n / 1024);
    if(result == 0) {
        sprintf(buff, "%ld", n);
        return buff;
    }
    else {
        sprintf(buff, "%dK", result);
        return buff;
    }
}
実行例:

$ ./dir -l .
<DIR> 775 .. 4K 6 1970年 1月 1日(木) 9時00分00秒
   664 directory.html 10K 1 2013年 1月 3日(木) 19時45分05秒
   644 dir_source.txt 3K 1 2013年 1月 3日(木) 19時50分38秒
<DIR> 775 . 4K 2 2013年 1月 3日(木) 19時51分49秒