[C言語] ディレクトリ内のファイルの名前を取得する方法

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

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

その後、readdir関数を用いてstruct direntを取得し、d_nameメンバーを参照することでファイル名を取得できます。

ディレクトリの操作が終わったら、closedir関数でディレクトリを閉じることを忘れないようにしましょう。

この方法はUnix系システムで一般的に使用されます。

この記事でわかること
  • opendir、readdir、closedir関数を使用したファイル名の取得方法
  • dirent構造体の理解と活用
  • ファイル名のソートや特定の拡張子のファイルをリストアップする方法
  • 再帰的にサブディレクトリを探索する方法
  • Windows環境での対応方法とC言語の利点

目次から探す

ディレクトリ内のファイル名を取得する方法

ディレクトリ内のファイル名を取得することは、ファイル操作を行う上で基本的な技術です。

C言語では、標準ライブラリを使用してディレクトリを操作し、ファイル名を取得することができます。

以下では、具体的な関数と構造体を用いてその方法を解説します。

opendir関数とreaddir関数の使用

opendir関数readdir関数は、ディレクトリを開いてその中のファイル名を取得するために使用されます。

  • opendir関数

opendir関数は、指定したディレクトリを開き、ディレクトリストリームへのポインタを返します。

ディレクトリが存在しない場合や開けない場合は、NULLを返します。

  • readdir関数

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

読み込んだエントリはdirent構造体として返されます。

以下に、opendirreaddirを使用したサンプルコードを示します。

#include <stdio.h>
#include <dirent.h>
int main() {
    // ディレクトリを開く
    DIR *dir = opendir(".");
    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;
}
ファイル名: .
ファイル名: ..
ファイル名: file1.txt
ファイル名: file2.c

このプログラムは、カレントディレクトリ内のすべてのファイル名を表示します。

opendirでディレクトリを開き、readdirで各ファイル名を取得して表示しています。

dirent構造体の理解

dirent構造体は、readdir関数によって返されるディレクトリエントリを表します。

この構造体には、ファイル名やファイルの種類に関する情報が含まれています。

  • 主要なメンバー
  • d_name: ファイル名を格納する文字列
  • d_type: ファイルの種類を示す(通常は使用しない)

d_nameは、ファイル名を取得するために最もよく使用されるメンバーです。

d_typeは、ファイルが通常のファイルかディレクトリかを判別するために使用されることがありますが、プラットフォームによってはサポートされていない場合があります。

closedir関数でのディレクトリのクローズ

closedir関数は、opendirで開いたディレクトリストリームを閉じるために使用されます。

ディレクトリを操作し終わったら、必ずclosedirを呼び出してリソースを解放することが重要です。

  • 使用方法
  • closedir(DIR *dirp);

dirpは、opendirで取得したディレクトリストリームへのポインタです。

closedirを呼び出さないと、リソースリークが発生する可能性があります。

これは、特に長時間実行されるプログラムや多くのディレクトリを操作するプログラムにおいて問題となります。

応用例

ディレクトリ内のファイル名を取得する基本的な方法を理解したところで、さらに応用的な操作を行う方法を紹介します。

これらの応用例は、実際のプログラム開発において非常に役立ちます。

ファイル名のソート

取得したファイル名をソートすることで、アルファベット順やサイズ順にファイルを整理することができます。

C言語では、標準ライブラリのqsort関数を使用してファイル名をソートすることが可能です。

以下に、ファイル名をアルファベット順にソートするサンプルコードを示します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int compare(const void *a, const void *b) {
    return strcmp(*(const char **)a, *(const char **)b);
}
int main() {
    DIR *dir = opendir(".");
    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);
    }
    closedir(dir);
    qsort(filenames, count, sizeof(char *), compare);
    for (int i = 0; i < count; i++) {
        printf("ファイル名: %s\n", filenames[i]);
        free(filenames[i]);
    }
    return 0;
}

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

特定の拡張子のファイルをリストアップ

特定の拡張子を持つファイルのみをリストアップすることは、ファイル操作の効率を高めるために有用です。

以下のサンプルコードでは、.txt拡張子を持つファイルのみをリストアップします。

#include <stdio.h>
#include <string.h>
#include <dirent.h>
int main() {
    DIR *dir = opendir(".");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strstr(entry->d_name, ".txt") != NULL) {
            printf("テキストファイル: %s\n", entry->d_name);
        }
    }
    closedir(dir);
    return 0;
}

このプログラムは、カレントディレクトリ内の.txtファイルのみを表示します。

strstr関数を使用して、ファイル名に特定の拡張子が含まれているかを確認しています。

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

ディレクトリ内のファイルを再帰的に探索することで、サブディレクトリ内のファイルも含めてリストアップすることができます。

以下のサンプルコードでは、再帰的にディレクトリを探索してすべてのファイルを表示します。

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void listFiles(const char *path) {
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        char fullPath[1024];
        snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name);
        struct stat statbuf;
        if (stat(fullPath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
            listFiles(fullPath);
        } else {
            printf("ファイル: %s\n", fullPath);
        }
    }
    closedir(dir);
}
int main() {
    listFiles(".");
    return 0;
}
ファイル: ./.vscode/c_cpp_properties.json
ファイル: ./.vscode/settings.json
ファイル: ./.vscode/tasks.json
ファイル: ./main.c
ファイル: ./main.exe
ファイル: ./sample.csv
ファイル: ./tempCodeRunnerFile.c

このプログラムは、指定されたディレクトリから開始して、すべてのサブディレクトリを再帰的に探索し、ファイル名を表示します。

stat関数を使用して、エントリがディレクトリかどうかを判定しています。

よくある質問

Windows環境でも同じ方法で取得できるのか?

C言語でディレクトリ内のファイル名を取得する方法は、POSIX標準に基づいています。

そのため、LinuxやUNIX系のシステムでは問題なく動作しますが、Windows環境では直接的には動作しません。

Windowsでは、dirent.hをサポートするライブラリを使用するか、Windows APIを利用してディレクトリ操作を行う必要があります。

例えば、Windows APIのFindFirstFileFindNextFileを使用することで、同様の機能を実現できます。

ファイル名の取得に失敗する原因は?

ファイル名の取得に失敗する原因はいくつか考えられます。

主な原因としては以下のようなものがあります。

  • ディレクトリが存在しない: 指定したディレクトリが存在しない場合、opendirNULLを返します。
  • アクセス権限がない: ディレクトリに対する読み取り権限がない場合、ディレクトリを開くことができません。
  • メモリ不足: 大量のファイル名を格納するためのメモリが不足している場合、プログラムが正常に動作しないことがあります。

他のプログラミング言語と比較してC言語の利点は?

C言語は、システムプログラミングや組み込みシステムで広く使用されている低レベルのプログラミング言語です。

他のプログラミング言語と比較した際の利点としては以下の点が挙げられます。

  • 高いパフォーマンス: C言語はコンパイルされたコードが非常に効率的であり、実行速度が速いです。
  • ハードウェアへの直接アクセス: C言語はポインタを使用してメモリやハードウェアに直接アクセスできるため、システムリソースを細かく制御できます。
  • 移植性: C言語で書かれたコードは、適切に書かれていれば、異なるプラットフォーム間で比較的容易に移植できます。

まとめ

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

この記事では、opendirreaddirclosedir関数を使用したファイル名の取得方法と、その応用例について解説しました。

これらの知識を活用して、より効率的なファイル操作を行いましょう。

  • URLをコピーしました!
目次から探す