ファイル

[C言語] ディレクトリにあるファイル一覧を取得する方法

C言語でディレクトリ内のファイル一覧を取得するには、POSIX標準のライブラリを使用します。

具体的には、dirent.hヘッダーファイルをインクルードし、opendir関数でディレクトリを開きます。

その後、readdir関数を用いてstruct direntを取得し、ディレクトリエントリを順次読み取ります。

読み取りが完了したら、closedir関数でディレクトリを閉じます。

この方法はUnix系システムで一般的に使用されますが、Windowsでは異なるAPIを使用する必要があります。

opendir, readdir, closedir関数の使い方

C言語でディレクトリ内のファイル一覧を取得するためには、opendirreaddirclosedirという3つの関数を使用します。

これらの関数は、POSIX標準に準拠しており、UNIX系のシステムで広く利用されています。

以下では、それぞれの関数の役割と使い方について詳しく解説します。

opendir関数の役割と使い方

opendir関数は、指定したディレクトリを開き、そのディレクトリに対するディレクトリストリームを返します。

このストリームを使用して、ディレクトリ内のファイルを順次読み込むことができます。

#include <stdio.h>
#include <dirent.h>
int main() {
    // ディレクトリを開く
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    // ディレクトリが正常に開かれた場合の処理
    closedir(dir);
    return 0;
}

この例では、opendir関数を使用してディレクトリを開き、エラーが発生した場合にはperror関数でエラーメッセージを表示しています。

readdir関数でファイルを読み込む

readdir関数は、opendirで開いたディレクトリストリームから次のディレクトリエントリを読み込みます。

読み込んだエントリはstruct dirent型のポインタとして返されます。

#include <stdio.h>
#include <dirent.h>
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    // ディレクトリ内のファイルを順次読み込む
    while ((entry = readdir(dir)) != NULL) {
        printf("ファイル名: %s\n", entry->d_name);
    }
    closedir(dir);
    return 0;
}

このコードでは、readdir関数を使ってディレクトリ内のすべてのファイル名を表示しています。

closedir関数でディレクトリを閉じる

closedir関数は、opendirで開いたディレクトリストリームを閉じます。

ディレクトリの操作が完了したら、必ずこの関数を呼び出してリソースを解放する必要があります。

#include <stdio.h>
#include <dirent.h>
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    // ディレクトリ内のファイルを読み込む処理
    closedir(dir); // ディレクトリを閉じる
    return 0;
}

closedir関数を呼び出すことで、ディレクトリストリームを適切に閉じ、システムリソースを解放します。

エラーハンドリングの実装

ディレクトリ操作中にエラーが発生することがあります。

これらのエラーを適切に処理するためには、各関数の戻り値を確認し、エラーが発生した場合には適切な処理を行うことが重要です。

  • opendirNULLを返した場合、ディレクトリが存在しないか、アクセス権がない可能性があります。
  • readdirNULLを返した場合、ディレクトリの終端に達したか、エラーが発生した可能性があります。
  • closedir-1を返した場合、ディレクトリストリームのクローズに失敗した可能性があります。

エラーハンドリングの例:

#include <stdio.h>
#include <dirent.h>
#include <errno.h>
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("ファイル名: %s\n", entry->d_name);
    }
    if (closedir(dir) == -1) {
        perror("closedir");
        return 1;
    }
    return 0;
}

この例では、perror関数を使用して、エラーが発生した場合にエラーメッセージを表示しています。

これにより、問題の原因を特定しやすくなります。

ファイル一覧を取得するプログラムの実装

ディレクトリ内のファイル一覧を取得するプログラムを実装する際には、opendirreaddirclosedir関数を組み合わせて使用します。

ここでは、基本的なプログラムの流れから、ファイル名の出力、ファイル属性の取得、サブディレクトリの処理までを解説します。

基本的なプログラムの流れ

ディレクトリ内のファイル一覧を取得するプログラムの基本的な流れは以下の通りです。

  1. opendir関数でディレクトリを開く。
  2. readdir関数でディレクトリ内のファイルを順次読み込む。
  3. 必要に応じてファイル名や属性を処理する。
  4. closedir関数でディレクトリを閉じる。

以下は、基本的なプログラムの例です。

#include <stdio.h>
#include <dirent.h>
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("ファイル名: %s\n", entry->d_name);
    }
    closedir(dir);
    return 0;
}

ファイル名の出力

readdir関数を使用して取得したstruct dirent型のポインタから、ファイル名を取得して出力することができます。

d_nameメンバーを使用してファイル名を取得します。

#include <stdio.h>
#include <dirent.h>
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("ファイル名: %s\n", entry->d_name);
    }
    closedir(dir);
    return 0;
}

このプログラムは、指定したディレクトリ内のすべてのファイル名を標準出力に表示します。

ファイル属性の取得

ファイルの属性を取得するためには、stat関数を使用します。

stat関数は、ファイルの詳細な情報を取得するために使用されます。

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    struct stat fileStat;
    while ((entry = readdir(dir)) != NULL) {
        if (stat(entry->d_name, &fileStat) == 0) {
            printf("ファイル名: %s, サイズ: %ldバイト\n", entry->d_name, fileStat.st_size);
        } else {
            perror("stat");
        }
    }
    closedir(dir);
    return 0;
}

このプログラムは、各ファイルの名前とサイズを表示します。

サブディレクトリの処理

サブディレクトリを処理するためには、再帰的にディレクトリを探索する必要があります。

readdirで取得したエントリがディレクトリであるかどうかを確認し、ディレクトリであれば再帰的に処理を行います。

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
void listFiles(const char *path) {
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return;
    }
    struct dirent *entry;
    struct stat fileStat;
    char fullPath[1024];
    while ((entry = readdir(dir)) != NULL) {
        snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name);
        if (stat(fullPath, &fileStat) == 0) {
            if (S_ISDIR(fileStat.st_mode)) {
                // サブディレクトリの場合
                if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                    printf("ディレクトリ: %s\n", fullPath);
                    listFiles(fullPath); // 再帰的に処理
                }
            } else {
                // ファイルの場合
                printf("ファイル: %s\n", fullPath);
            }
        } else {
            perror("stat");
        }
    }
    closedir(dir);
}
int main() {
    listFiles("/path/to/directory");
    return 0;
}

このプログラムは、指定したディレクトリ内のすべてのファイルとサブディレクトリを再帰的に探索し、それぞれのパスを表示します。

サブディレクトリを再帰的に処理することで、ディレクトリツリー全体を探索することができます。

応用例

ディレクトリ内のファイル一覧を取得する基本的な方法を理解したら、次はその応用例を考えてみましょう。

ここでは、ファイル一覧をソートする方法、特定の拡張子のファイルのみを表示する方法、再帰的にサブディレクトリを探索する方法について解説します。

ファイル一覧をソートする

ファイル一覧をソートするには、取得したファイル名を配列に格納し、qsort関数を使用してソートします。

以下の例では、ファイル名をアルファベット順にソートしています。

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *a, const void *b) {
    return strcmp(*(const char **)a, *(const char **)b);
}
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    char *fileNames[100];
    int count = 0;
    while ((entry = readdir(dir)) != NULL) {
        fileNames[count] = strdup(entry->d_name);
        count++;
    }
    qsort(fileNames, count, sizeof(char *), compare);
    for (int i = 0; i < count; i++) {
        printf("ファイル名: %s\n", fileNames[i]);
        free(fileNames[i]);
    }
    closedir(dir);
    return 0;
}

このプログラムは、ディレクトリ内のファイル名を取得し、アルファベット順にソートして表示します。

特定の拡張子のファイルのみを表示

特定の拡張子を持つファイルのみを表示するには、ファイル名の末尾をチェックします。

以下の例では、.txt拡張子を持つファイルのみを表示しています。

#include <stdio.h>
#include <dirent.h>
#include <string.h>
int hasExtension(const char *fileName, const char *ext) {
    const char *dot = strrchr(fileName, '.');
    return dot && strcmp(dot, ext) == 0;
}
int main() {
    DIR *dir = opendir("/path/to/directory");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (hasExtension(entry->d_name, ".txt")) {
            printf("テキストファイル: %s\n", entry->d_name);
        }
    }
    closedir(dir);
    return 0;
}

このプログラムは、.txt拡張子を持つファイルのみを表示します。

再帰的にサブディレクトリを探索する

再帰的にサブディレクトリを探索するには、前述の再帰的な処理を行うプログラムを使用します。

以下の例では、ディレクトリツリー全体を探索し、すべてのファイルとディレクトリを表示します。

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
void listFiles(const char *path) {
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return;
    }
    struct dirent *entry;
    struct stat fileStat;
    char fullPath[1024];
    while ((entry = readdir(dir)) != NULL) {
        snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name);
        if (stat(fullPath, &fileStat) == 0) {
            if (S_ISDIR(fileStat.st_mode)) {
                // サブディレクトリの場合
                if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                    printf("ディレクトリ: %s\n", fullPath);
                    listFiles(fullPath); // 再帰的に処理
                }
            } else {
                // ファイルの場合
                printf("ファイル: %s\n", fullPath);
            }
        } else {
            perror("stat");
        }
    }
    closedir(dir);
}
int main() {
    listFiles("/path/to/directory");
    return 0;
}

このプログラムは、指定したディレクトリ内のすべてのファイルとサブディレクトリを再帰的に探索し、それぞれのパスを表示します。

再帰的な処理を行うことで、ディレクトリツリー全体を探索することができます。

まとめ

ディレクトリ内のファイル一覧を取得する方法は、C言語の基本的なファイル操作の一部です。

この記事では、opendirreaddirclosedir関数を使用した基本的なファイル一覧の取得方法から、応用例としてのソートや特定の拡張子のファイル表示、再帰的なサブディレクトリ探索までを解説しました。

これらの知識を活用して、より高度なファイル操作を実装してみてください。

関連記事

Back to top button