【C言語】フォルダ内のファイルを検索する方法を解説

この記事では、C言語を使ってフォルダ内のファイルを検索する方法をわかりやすく解説します。

ディレクトリの中にあるファイルを取得するための基本的な関数の使い方や、特定のファイルを見つけるためのフィルタリング方法について学ぶことができます。

初心者の方でも理解できるように、サンプルコードとその解説を交えながら進めていきますので、ぜひ最後までご覧ください。

目次から探す

フォルダ内のファイルを検索する手順

C言語を使ってフォルダ内のファイルを検索するには、まずディレクトリのエントリを取得し、その後必要なファイルをフィルタリングする必要があります。

このプロセスを詳しく見ていきましょう。

ディレクトリのエントリを取得

ディレクトリ内のファイルを取得するためには、opendirreaddirclosedirといった関数を使用します。

これらの関数を使うことで、指定したディレクトリの中にあるファイルやサブディレクトリの情報を取得できます。

readdir関数の使い方

readdir関数は、オープンしたディレクトリから次のエントリを読み取るために使用されます。

以下は、readdir関数の基本的な使い方を示すサンプルコードです。

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int main() {
    DIR *dir;
    struct dirent *entry;
    // ディレクトリをオープン
    dir = opendir("path/to/directory");
    if (dir == NULL) {
        perror("ディレクトリをオープンできません");
        return EXIT_FAILURE;
    }
    // ディレクトリエントリを読み取る
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name); // エントリ名を表示
    }
    // ディレクトリをクローズ
    closedir(dir);
    return EXIT_SUCCESS;
}

このコードでは、指定したパスのディレクトリをオープンし、readdirを使ってすべてのエントリ名を表示しています。

d_nameは、エントリの名前を格納している構造体のメンバーです。

ディレクトリエントリの構造

readdir関数が返すエントリは、struct direntという構造体で表されます。

この構造体には、以下のようなメンバーがあります。

項目説明
d_inoエントリのiノード番号
d_typeエントリのタイプ (ファイル、ディレクトリなど)
d_nameエントリの名前

これらの情報を使って、ファイルの種類を判別したり、特定のファイルを検索したりすることができます。

ファイル名のフィルタリング

ディレクトリ内のすべてのファイルを取得した後、特定の条件に基づいてファイルをフィルタリングすることができます。

ここでは、特定の拡張子を持つファイルの検索と、ファイル名のパターンマッチングについて説明します。

特定の拡張子を持つファイルの検索

特定の拡張子を持つファイルを検索するには、ファイル名の末尾をチェックする必要があります。

以下は、.txt拡張子を持つファイルを検索する例です。

#include <string.h>
// .txt拡張子を持つファイルを検索
if (strstr(entry->d_name, ".txt") != NULL) {
    printf("見つかったファイル: %s\n", entry->d_name);
}

このコードでは、strstr関数を使ってファイル名に.txtが含まれているかを確認しています。

ファイル名のパターンマッチング

ファイル名のパターンマッチングを行うには、正規表現を使用することが一般的です。

C言語では、regex.hライブラリを使って正規表現を扱うことができます。

以下は、特定のパターンにマッチするファイル名を検索する例です。

#include <regex.h>
regex_t regex;
regcomp(®ex, "^file[0-9]+\\.txt$", 0); // "file"で始まり、数字が続き、".txt"で終わるパターン
if (regexec(®ex, entry->d_name, 0, NULL, 0) == 0) {
    printf("パターンにマッチしたファイル: %s\n", entry->d_name);
}
regfree(®ex);

このコードでは、regcompで正規表現をコンパイルし、regexecでファイル名がそのパターンにマッチするかを確認しています。

以上の手順を踏むことで、C言語を使ってフォルダ内のファイルを効率的に検索することができます。

ディレクトリのエントリを取得し、必要なファイルをフィルタリングすることで、目的のファイルを見つけることができるでしょう。

実際のコード例

基本的なファイル検索プログラム

フォルダ内のファイルを検索する基本的なプログラムを以下に示します。

このプログラムは、指定したディレクトリ内のすべてのファイルをリストアップします。

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
void search_files(const char *dir_name) {
    struct dirent *entry;
    DIR *dp = opendir(dir_name);
    // ディレクトリが開けない場合のエラーハンドリング
    if (dp == NULL) {
        perror("opendir");
        return;
    }
    // ディレクトリ内のエントリを読み込む
    while ((entry = readdir(dp)) != NULL) {
        // "." と ".." をスキップ
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            printf("%s\n", entry->d_name); // ファイル名を表示
        }
    }
    closedir(dp); // ディレクトリを閉じる
}
int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <directory>\n", argv[0]);
        return EXIT_FAILURE;
    }
    search_files(argv[1]); // 引数で指定されたディレクトリを検索
    return EXIT_SUCCESS;
}

コードの全体構成

このプログラムは、以下の主要な部分で構成されています。

  1. インクルードディレクティブ: 必要なライブラリをインクルードします。

<stdio.h>は標準入出力、<stdlib.h>は標準ライブラリ、<dirent.h>はディレクトリ操作、<string.h>は文字列操作に使用します。

  1. search_files関数: 指定されたディレクトリ内のファイルを検索し、ファイル名を表示します。
  2. main関数: プログラムのエントリーポイントで、コマンドライン引数を処理し、search_files関数を呼び出します。

各部分の解説

  • opendir関数: 指定したディレクトリを開き、成功した場合はそのポインタを返します。

失敗した場合はNULLを返します。

  • readdir関数: 開いたディレクトリから次のエントリを読み込みます。

すべてのエントリを読み込むまでループを続けます。

  • strcmp関数: 文字列を比較し、同じでない場合にファイル名を表示します。

これにより、カレントディレクトリ(.)と親ディレクトリ(..)をスキップします。

  • closedir関数: 開いたディレクトリを閉じます。

リソースの解放に重要です。

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

プログラムでは、エラーハンドリングが重要です。

特に、ディレクトリを開く際に失敗する可能性があるため、適切なエラーメッセージを表示することが求められます。

エラー処理の重要性

エラー処理を行うことで、プログラムが予期しない動作をすることを防ぎ、ユーザーに適切な情報を提供できます。

例えば、指定したディレクトリが存在しない場合や、アクセス権がない場合には、エラーメッセージを表示してプログラムを終了させることが重要です。

errnoの利用方法

C言語では、エラーが発生した場合にerrnoというグローバル変数が設定されます。

これを利用して、エラーの種類を特定することができます。

以下は、errnoを使用したエラーメッセージの表示例です。

#include <errno.h>
#include <string.h>
// エラーハンドリングの例
if (dp == NULL) {
    fprintf(stderr, "Error opening directory: %s\n", strerror(errno));
    return;
}

このように、strerror関数を使ってerrnoの値に基づくエラーメッセージを表示することで、ユーザーに具体的なエラーの内容を伝えることができます。

これにより、デバッグが容易になり、プログラムの信頼性が向上します。

目次から探す