はじめに なぜ「ディレクトリ一覧取得」が業務で重要なのか
業務システムでは、ファイルだけでなく「フォルダ(ディレクトリ)」を扱う場面が非常に多いです。
たとえば次のようなケースです。
- 日付ごとにフォルダが作られており、最新フォルダだけ処理したい
- バックアップフォルダの中から、古い日付のフォルダを削除したい
- サブフォルダを含めて構造を調べたい
- 特定の名前パターンのフォルダだけを対象にしたい
こうした処理の入り口になるのが「ディレクトリ一覧取得」です。
C# では Directory.GetDirectories と Directory.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.Exists や SearchOption を書くのは面倒なので、ユーティリティ化しておくと便利です。
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を使う - 更新日時順に並べ替えるユーティリティを用意しておく
- 権限エラーや存在チェックをユーティリティ側で吸収する
ここまで押さえておけば、「最新フォルダだけ処理したい」「特定のフォルダだけ対象にしたい」といった業務要件に柔軟に対応できます。
