C# Tips | ファイル・ディレクトリ操作:ディレクトリ一覧取得

C sharp C#
スポンサーリンク

はじめに なぜ「ディレクトリ一覧取得」が業務で重要なのか

業務システムでは、ファイルだけでなく「フォルダ(ディレクトリ)」を扱う場面が非常に多いです。
たとえば次のようなケースです。

  • 日付ごとにフォルダが作られており、最新フォルダだけ処理したい
  • バックアップフォルダの中から、古い日付のフォルダを削除したい
  • サブフォルダを含めて構造を調べたい
  • 特定の名前パターンのフォルダだけを対象にしたい

こうした処理の入り口になるのが「ディレクトリ一覧取得」です。
C# では Directory.GetDirectoriesDirectory.EnumerateDirectories を使うことで、簡単にフォルダ一覧を取得できます。

ここでは、初心者でも理解しやすいように、基本から実務レベルのユーティリティ化まで丁寧に解説します。


基本の API Directory.GetDirectories の使い方

指定フォルダ直下のディレクトリ一覧を取得する

最も基本的な書き方は次のとおりです。

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string root = @"C:\data";

        string[] dirs = Directory.GetDirectories(root);

        foreach (string dir in dirs)
        {
            Console.WriteLine(dir);
        }
    }
}
C#

Directory.GetDirectories(path) は「指定フォルダ直下のディレクトリ一覧」を返します。

ここで重要なのは、

  • ファイルは返さない(フォルダだけ)
  • サブフォルダの中までは見に行かない

という点です。

パターン指定で絞り込む(例:日付フォルダだけ)

ファイルと同じように、フォルダ名にもワイルドカードを使えます。

string[] dateDirs = Directory.GetDirectories(root, "2025*");
C#

これは「2025 で始まるフォルダだけ」を取得します。

業務では「YYYYMMDD 形式のフォルダだけ処理したい」などの要件が多いので、パターン検索は非常に便利です。

サブフォルダも含めて検索する SearchOption

フォルダ構造全体を調べたい場合は、第三引数に SearchOption.AllDirectories を指定します。

string[] allDirs = Directory.GetDirectories(
    root,
    "*",
    SearchOption.AllDirectories);
C#

これにより、配下のすべてのサブフォルダを再帰的に検索します。


Directory.EnumerateDirectories の使いどころ

GetDirectories との違い

Directory.GetDirectories は「すべての結果を配列に読み込んでから返す」メソッドです。
一方、Directory.EnumerateDirectories は「見つけた順に返す」ストリーミング型のメソッドです。

大量のフォルダを扱う場合は、EnumerateDirectories のほうがメモリ効率が良くなります。

foreach (string dir in Directory.EnumerateDirectories(root, "*", SearchOption.AllDirectories))
{
    Console.WriteLine(dir);
}
C#

初心者向けの目安としては、

  • フォルダ数が少ない → GetDirectories
  • フォルダ数が多い → EnumerateDirectories

と覚えておけば十分です。


実務で使えるディレクトリ一覧ユーティリティ

基本の一覧取得ユーティリティ(直下/再帰切り替え)

毎回 Directory.ExistsSearchOption を書くのは面倒なので、ユーティリティ化しておくと便利です。

using System;
using System.IO;

public static class DirectoryListUtil
{
    public static string[] GetDirectoryList(
        string directoryPath,
        bool includeSubDirectories = false)
    {
        if (!Directory.Exists(directoryPath))
        {
            throw new DirectoryNotFoundException($"ディレクトリが見つかりません: {directoryPath}");
        }

        SearchOption option = includeSubDirectories
            ? SearchOption.AllDirectories
            : SearchOption.TopDirectoryOnly;

        return Directory.GetDirectories(directoryPath, "*", option);
    }
}
C#

使い方の例:

string[] dirs = DirectoryListUtil.GetDirectoryList(
    @"C:\data",
    includeSubDirectories: true);

foreach (string d in dirs)
{
    Console.WriteLine(d);
}
C#

パターン検索対応版

フォルダ名で絞り込みたい場合はこちら。

public static class DirectoryListUtil
{
    public static string[] GetDirectoryList(
        string directoryPath,
        string searchPattern,
        bool includeSubDirectories = false)
    {
        if (!Directory.Exists(directoryPath))
        {
            throw new DirectoryNotFoundException($"ディレクトリが見つかりません: {directoryPath}");
        }

        if (string.IsNullOrWhiteSpace(searchPattern))
        {
            searchPattern = "*";
        }

        SearchOption option = includeSubDirectories
            ? SearchOption.AllDirectories
            : SearchOption.TopDirectoryOnly;

        return Directory.GetDirectories(directoryPath, searchPattern, option);
    }
}
C#

例:

string[] yearDirs = DirectoryListUtil.GetDirectoryList(
    @"C:\logs",
    "2025*",
    includeSubDirectories: false);
C#

ディレクトリ一覧を「並べ替える」ユーティリティ

更新日時順に並べる(新しい順・古い順)

フォルダの更新日時で並べたい場合は、DirectoryInfo を使います。

using System;
using System.IO;
using System.Linq;

public static class DirectorySortUtil
{
    public static DirectoryInfo[] GetDirectoriesSortedByLastWriteTime(
        string directoryPath,
        string searchPattern = "*",
        bool includeSubDirectories = false,
        bool descending = false)
    {
        if (!Directory.Exists(directoryPath))
        {
            throw new DirectoryNotFoundException($"ディレクトリが見つかりません: {directoryPath}");
        }

        SearchOption option = includeSubDirectories
            ? SearchOption.AllDirectories
            : SearchOption.TopDirectoryOnly;

        string[] paths = Directory.GetDirectories(directoryPath, searchPattern, option);

        var query = paths.Select(p => new DirectoryInfo(p));

        return descending
            ? query.OrderByDescending(d => d.LastWriteTime).ToArray()
            : query.OrderBy(d => d.LastWriteTime).ToArray();
    }
}
C#

例:

var dirs = DirectorySortUtil.GetDirectoriesSortedByLastWriteTime(
    @"C:\logs",
    "*",
    includeSubDirectories: false,
    descending: true);

foreach (var d in dirs)
{
    Console.WriteLine($"{d.LastWriteTime:yyyy-MM-dd HH:mm:ss}  {d.FullName}");
}
C#

業務では「最新フォルダだけ処理したい」という要件が多いので、更新日時ソートは非常に役立ちます。


再帰的なディレクトリ探索の注意点

無限ループに注意(シンボリックリンク)

Windows では、フォルダに「ジャンクション」や「シンボリックリンク」が存在することがあります。
これを再帰検索すると、リンク先が自分自身を指している場合に無限ループになる可能性があります。

業務システムでは、

  • シンボリックリンクを無視する
  • 特定のフォルダを除外する

といった対策を入れることがあります。

権限エラーに注意

サブフォルダを再帰的に検索すると、権限のないフォルダに遭遇することがあります。
その場合は UnauthorizedAccessException が発生します。

実務では try-catch でスキップすることもあります。


例外とエラー処理を意識したディレクトリ一覧取得

起こり得る例外

  • ディレクトリが存在しない
  • 権限がなくて中身を列挙できない
  • ネットワークドライブの接続が切れている
  • パスが長すぎる

これらはすべて「一覧取得に失敗した理由」です。

呼び出し側での例外処理例

try
{
    var dirs = DirectoryListUtil.GetDirectoryList(@"C:\data", "*", true);

    foreach (var d in dirs)
    {
        Console.WriteLine(d);
    }
}
catch (DirectoryNotFoundException ex)
{
    Console.WriteLine("ディレクトリが見つかりません: " + ex.Message);
}
catch (UnauthorizedAccessException ex)
{
    Console.WriteLine("権限エラー: " + ex.Message);
}
catch (IOException ex)
{
    Console.WriteLine("入出力エラー: " + ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("想定外のエラー: " + ex.Message);
}
C#

まとめ 実務で使える「ディレクトリ一覧取得」ユーティリティの考え方

ディレクトリ一覧取得は、ファイル処理の前段階として非常に重要です。
だからこそ、次のポイントを押さえておくと業務コードが安定します。

  • Directory.GetDirectories で直下のフォルダ一覧を取得する
  • SearchOption.AllDirectories で再帰検索ができる
  • パターン検索("2025*" など)で柔軟に絞り込める
  • 大量フォルダなら EnumerateDirectories を使う
  • 更新日時順に並べ替えるユーティリティを用意しておく
  • 権限エラーや存在チェックをユーティリティ側で吸収する

ここまで押さえておけば、「最新フォルダだけ処理したい」「特定のフォルダだけ対象にしたい」といった業務要件に柔軟に対応できます。

タイトルとURLをコピーしました