【C++17】filesystemでディレクトリ内のファイル一覧を列挙する方法

目次

はじめに

C++で、特定のディレクトリに含まれる全てのファイルやフォルダの一覧を取得したい、という場面は頻繁にあります。

C++17で導入された <filesystem> ライブラリは、この「ディレクトリ内のエントリ(ファイルやフォルダ)を走査する」ための、2種類の特殊なイテレータを提供しています。

  1. std::filesystem::directory_iterator: 指定したディレクトリの直下にあるエントリだけを列挙します。
  2. std::filesystem::recursive_directory_iterator: 指定したディレクトリと、その全てのサブディレクトリの中身を、再帰的に深く辿って列挙します。

【前提】C++17とは?

C++17は、2017年に正式化されたC++言語の規格です。<filesystem> ライブラリはこのC++17で導入されたため、利用するにはC++17に対応したコンパイラと、適切なコンパイラ設定(および、一部の環境ではリンカ設定)が必要になります。


ディレクトリを走査するサンプルコード

このコードは、まずテスト用のディレクトリとファイルを作成します。その後、directory_iteratorrecursive_directory_iterator の両方を使って、それぞれの走査結果の違いを表示します。

完成コード

#include <iostream>
#include <filesystem>
#include <fstream>
#include <vector>

// filesystem名前空間のエイリアス
namespace fs = std::filesystem;

int main() {
    // --- テスト用のディレクトリ構造を作成 ---
    // ./test_root/
    //   ├─ file1.txt
    //   └─ sub_dir/
    //        └─ file2.txt
    fs::path root_dir = "test_root";
    fs::create_directory(root_dir);
    fs::create_directory(root_dir / "sub_dir");
    std::ofstream(root_dir / "file1.txt");
    std::ofstream(root_dir / "sub_dir" / "file2.txt");
    
    std::cout << "--- 1. directory_iterator (非再帰) ---" << std::endl;
    // 範囲for文で test_root の直下を走査
    for (const fs::directory_entry& entry : fs::directory_iterator(root_dir)) {
        std::cout << entry.path() << std::endl;
    }

    std::cout << "\n--- 2. recursive_directory_iterator (再帰) ---" << std::endl;
    // 範囲for文で test_root 以下を再帰的に走査
    for (const fs::directory_entry& entry : fs::recursive_directory_iterator(root_dir)) {
        std::cout << entry.path() << std::endl;
    }
    
    // --- 後片付け ---
    fs::remove_all(root_dir);

    return 0;
}

実行結果(OSによりパスの区切り文字は異なります)

--- 1. directory_iterator (非再帰) ---
"test_root/file1.txt"
"test_root/sub_dir"
--- 2. recursive_directory_iterator (再帰) ---
"test_root/file1.txt"
"test_root/sub_dir"
"test_root/sub_dir/file2.txt"

コードの解説

fs::directory_iterator(root_dir)

  • 機能: 指定したパス(root_dir)の直下にあるディレクトリとファイルを指すイテレータを作成します。
  • 使い方: 範囲for文と組み合わせるのが最も簡単です。ループごとに、fs::directory_entry オブジェクトが entry 変数に格納されます。
  • directory_entry: ファイルやディレクトリといった、個々のエントリに関する情報(パス、ファイル種別など)を保持するクラスです。.path() でパスを、.is_directory().is_regular_file() で種類を判定できます。

fs::recursive_directory_iterator(root_dir)

  • 機能: 指定したパス以下の全てのディレクトリを再帰的に辿り、見つかった全てのファイルとディレクトリを指すイテレータを作成します。
  • 結果: 実行結果が示すように、sub_dir の中にある file2.txt までもがリストアップされていることが分かります。

まとめ

今回は、C++17の <filesystem> ライブラリを使って、ディレクトリ内のエントリを列挙する方法を解説しました。

  • directory_iterator: 浅く、指定したディレクトリの直下だけを走査する。
  • recursive_directory_iterator: 深く、全てのサブディレクトリを再帰的に走査する。

これらのイテレータを範囲for文と組み合わせることで、ファイル検索や、ディレクトリツリーの処理といった、複雑なファイルシステム操作を、OSに依存しない、統一的でモダンなコードで記述することができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次