C# Directory.GetFilesの使い方|フォルダ内のファイル取得・拡張子検索・サブフォルダ対応まで解説

はじめに

C#でフォルダ内のファイルを取得したいときによく使うのが、Directory.GetFilesメソッドです。たとえば、「指定フォルダ内のすべてのファイルを取得したい」「.txt.csvだけを取得したい」「サブフォルダ内のファイルもまとめて検索したい」といった場面で活躍します。

Directory.GetFilesは、指定した条件に一致するファイルのパスをstring[]で返すシンプルなメソッドです。基本的な使い方は簡単ですが、拡張子検索、サブフォルダ検索、例外処理、大量ファイルを扱う場合の注意点まで理解しておくと、実務でも安全に使えます。

この記事では、C#のDirectory.GetFilesの基本から、拡張子検索、複数条件、サブフォルダ対応、EnumerateFilesとの使い分けまで、サンプルコード付きで解説します。

1. C#のDirectory.GetFilesとは

Directory.GetFilesは、System.IO.Directoryクラスに用意されている静的メソッドです。指定したディレクトリ内にあるファイルを検索し、条件に一致したファイル名をパス付きで取得できます。Microsoftの公式ドキュメントでも、Directory.GetFilesは「指定した条件を満たすファイルの名前を返す」メソッドとして説明されています。

1-1. Directory.GetFilesでできること

Directory.GetFilesでは、主に次のような処理ができます。

C#
string[] files = Directory.GetFiles(@"C:\Work");

このコードでは、C:\Workフォルダ直下にあるファイル一覧を取得できます。

さらに、検索パターンを指定すれば、特定の拡張子やファイル名に一致するファイルだけを取得できます。

C#
string[] textFiles = Directory.GetFiles(@"C:\Work", "*.txt");

この例では、C:\Workフォルダ内の.txtファイルだけを取得します。

サブフォルダも含めて検索したい場合は、SearchOption.AllDirectoriesを指定します。

C#
string[] allTextFiles = Directory.GetFiles(
@"C:\Work",
"*.txt",
SearchOption.AllDirectories
);

1-2. Directory.GetFilesを使う主な場面

Directory.GetFilesは、次のような場面でよく使われます。

ファイル一覧を画面に表示したい場合、ログファイルをまとめて読み込みたい場合、画像ファイルを一括処理したい場合、CSVファイルを読み込んでデータ処理したい場合、バックアップ対象のファイルを抽出したい場合などです。

たとえば、アプリケーションのログフォルダから.logファイルを取得する処理は、次のように書けます。

C#
string logFolder = @"C:\App\Logs";
string[] logFiles = Directory.GetFiles(logFolder, "*.log");

foreach (string file in logFiles)
{
Console.WriteLine(file);
}

1-3. Directory.GetFilesとDirectoryInfo.GetFilesの違い

Directory.GetFilesと似たメソッドに、DirectoryInfo.GetFilesがあります。

Directory.GetFilesは静的メソッドなので、インスタンスを作らずに呼び出せます。

C#
string[] files = Directory.GetFiles(@"C:\Work");

一方、DirectoryInfo.GetFilesDirectoryInfoオブジェクトを作成してから使います。

C#
DirectoryInfo dir = new DirectoryInfo(@"C:\Work");
FileInfo[] files = dir.GetFiles();

大きな違いは戻り値です。Directory.GetFilesstring[]を返しますが、DirectoryInfo.GetFilesFileInfo[]を返します。FileInfoには、ファイル名、拡張子、サイズ、更新日時などの情報が含まれるため、ファイルの詳細情報を扱いたい場合に便利です。公式ドキュメントでも、DirectoryInfo.GetFilesFileInfoオブジェクトの配列を返すメソッドとして説明されています。

単純にパスの一覧だけ欲しい場合はDirectory.GetFiles、ファイルサイズや更新日時なども頻繁に使う場合はDirectoryInfo.GetFilesを選ぶとよいでしょう。

1-4. Directory.GetFilesとEnumerateFilesの違い

Directory.GetFilesとよく比較されるのが、Directory.EnumerateFilesです。

Directory.GetFilesは、条件に一致するファイルをすべて取得してから配列として返します。一方、Directory.EnumerateFilesは、ファイルを列挙しながら順次処理できます。公式ドキュメントでも、GetFilesは配列全体が返されるまで待つ必要があり、EnumerateFilesはコレクション全体が返される前に列挙を開始できるため、多数のファイルを扱う場合はEnumerateFilesの方が効率的と説明されています。

少数のファイルをまとめて取得するならGetFilesで十分です。大量のファイルを1件ずつ処理するならEnumerateFilesの方が向いています。

2. Directory.GetFilesの基本的な使い方

2-1. 必要な名前空間

Directory.GetFilesを使うには、System.IO名前空間を使用します。

C#
using System;
using System.IO;

DirectoryFilePathFileInfoDirectoryInfoなど、ファイル操作に関するクラスは主にSystem.IOに含まれています。

2-2. フォルダ内のファイル一覧を取得する基本コード

指定したフォルダ内のファイル一覧を取得する基本コードは次のとおりです。

C#
using System;
using System.IO;

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

string[] files = Directory.GetFiles(folderPath);

foreach (string file in files)
{
Console.WriteLine(file);
}
}
}

このコードを実行すると、C:\Workフォルダ直下にあるファイルのパスが出力されます。

たとえば次のような結果になります。

C:\Work\sample.txt
C:\Work\data.csv
C:\Work\image.png

2-3. 戻り値の型と取得できるパス

Directory.GetFilesの戻り値はstring[]です。

C#
string[] files = Directory.GetFiles(@"C:\Work");

配列の各要素には、取得したファイルのパスが入ります。公式ドキュメントでは、戻り値は「指定したディレクトリ内のファイルの完全な名前、つまりパスを含む名前の配列」と説明されています。また、ファイルが見つからない場合は空の配列が返されます。

そのため、ファイルが見つからない場合でもnullになるわけではありません。

C#
string[] files = Directory.GetFiles(@"C:\EmptyFolder");

Console.WriteLine(files.Length); // 0

2-4. ファイル名だけを取り出す方法

Directory.GetFilesで取得できるのは基本的にパス付きの文字列です。ファイル名だけを取り出したい場合は、Path.GetFileNameを使います。

C#
string[] files = Directory.GetFiles(@"C:\Work");

foreach (string file in files)
{
string fileName = Path.GetFileName(file);
Console.WriteLine(fileName);
}

出力例は次のようになります。

sample.txt
data.csv
image.png

拡張子を除いたファイル名だけを取得したい場合は、Path.GetFileNameWithoutExtensionを使います。

C#
string nameWithoutExtension = Path.GetFileNameWithoutExtension(file);

拡張子だけを取得したい場合は、Path.GetExtensionを使います。

C#
string extension = Path.GetExtension(file);

2-5. ファイル一覧を画面に表示する方法

取得したファイル一覧を画面に表示するだけなら、foreachで配列を回すのが基本です。

C#
string folderPath = @"C:\Work";
string[] files = Directory.GetFiles(folderPath);

Console.WriteLine("ファイル一覧:");

foreach (string file in files)
{
Console.WriteLine(file);
}

ファイル名だけを見やすく表示したい場合は、次のようにします。

C#
foreach (string file in files)
{
Console.WriteLine(Path.GetFileName(file));
}

件数も表示したい場合は、Lengthプロパティを使います。

C#
Console.WriteLine($"ファイル数: {files.Length}");

3. Directory.GetFilesの構文と主なオーバーロード

Directory.GetFilesには複数のオーバーロードがあります。よく使うのは次の3つです。

C#
Directory.GetFiles(string path)

Directory.GetFiles(string path, string searchPattern)

Directory.GetFiles(string path, string searchPattern, SearchOption searchOption)

さらに、.NETではEnumerationOptionsを指定できるオーバーロードもありますが、まずは上記3つを理解しておくと多くのケースに対応できます。

3-1. Directory.GetFiles(string path)

最も基本的な形式です。

C#
string[] files = Directory.GetFiles(@"C:\Work");

指定したフォルダ直下にあるすべてのファイルを取得します。サブフォルダ内のファイルは取得されません。

C:\Work\a.txt
C:\Work\b.csv
C:\Work\image.png

pathには、検索対象のフォルダパスを指定します。

3-2. Directory.GetFiles(string path, string searchPattern)

検索パターンを指定する形式です。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

この例では、C:\Workフォルダ直下の.txtファイルだけを取得します。

ファイル名の先頭や末尾を指定することもできます。

C#
string[] files = Directory.GetFiles(@"C:\Work", "data*.csv");

この例では、data001.csvdata_backup.csvのように、dataで始まり.csvで終わるファイルを取得します。

3-3. Directory.GetFiles(string path, string searchPattern, SearchOption searchOption)

サブフォルダを含めるかどうかを指定する形式です。

C#
string[] files = Directory.GetFiles(
@"C:\Work",
"*.txt",
SearchOption.AllDirectories
);

SearchOption.AllDirectoriesを指定すると、指定フォルダだけでなく、その配下のサブフォルダも検索対象になります。

直下だけを検索したい場合は、SearchOption.TopDirectoryOnlyを指定します。

C#
string[] files = Directory.GetFiles(
@"C:\Work",
"*.txt",
SearchOption.TopDirectoryOnly
);

3-4. Directory.GetFilesで指定できる引数の意味

Directory.GetFilesでよく使う引数は、pathsearchPatternsearchOptionの3つです。

pathには、検索対象のフォルダパスを指定します。

C#
string path = @"C:\Work";

searchPatternには、検索条件を指定します。

C#
string searchPattern = "*.txt";

searchOptionには、サブフォルダを検索するかどうかを指定します。

C#
SearchOption option = SearchOption.AllDirectories;

まとめると、次のようになります。

C#
string[] files = Directory.GetFiles(path, searchPattern, option);

3-5. 相対パスと絶対パスの指定方法

Directory.GetFilespathには、絶対パスと相対パスのどちらも指定できます。公式ドキュメントでも、pathパラメーターには相対パスまたは絶対パスを指定でき、相対パスは現在の作業ディレクトリからの相対パスとして解釈されると説明されています。

絶対パスの例です。

C#
string[] files = Directory.GetFiles(@"C:\Work");

相対パスの例です。

C#
string[] files = Directory.GetFiles(@"Data");

この場合、アプリケーションの現在の作業ディレクトリを基準にDataフォルダが探されます。

現在の作業ディレクトリを確認したい場合は、次のようにします。

C#
Console.WriteLine(Directory.GetCurrentDirectory());

パスを組み立てる場合は、文字列連結ではなくPath.Combineを使うのが安全です。

C#
string basePath = @"C:\Work";
string folderName = "Data";

string folderPath = Path.Combine(basePath, folderName);
string[] files = Directory.GetFiles(folderPath);

4. 拡張子やファイル名で検索する方法

4-1. 特定の拡張子のファイルだけ取得する

特定の拡張子だけを取得したい場合は、searchPattern*.拡張子を指定します。

C#
string[] textFiles = Directory.GetFiles(@"C:\Work", "*.txt");

CSVファイルを取得する場合は次のようにします。

C#
string[] csvFiles = Directory.GetFiles(@"C:\Work", "*.csv");

画像ファイルのうちPNGだけを取得する場合は、次のように書けます。

C#
string[] pngFiles = Directory.GetFiles(@"C:\Images", "*.png");

4-2. 複数の拡張子を対象にする方法

Directory.GetFilessearchPatternには、*.jpg;*.pngのような複数条件を直接指定することはできません。複数の拡張子を対象にしたい場合は、拡張子ごとにGetFilesを呼び出して結合する方法がよく使われます。

C#
using System;
using System.IO;
using System.Linq;

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

string[] extensions = { "*.jpg", "*.png", "*.gif" };

string[] imageFiles = extensions
.SelectMany(ext => Directory.GetFiles(folderPath, ext))
.ToArray();

foreach (string file in imageFiles)
{
Console.WriteLine(file);
}
}
}

SearchOption.AllDirectoriesと組み合わせることもできます。

C#
string[] imageFiles = extensions
.SelectMany(ext => Directory.GetFiles(folderPath, ext, SearchOption.AllDirectories))
.ToArray();

また、すべてのファイルを取得してからPath.GetExtensionで絞り込む方法もあります。

C#
string[] imageFiles = Directory.GetFiles(@"C:\Images")
.Where(file =>
{
string ext = Path.GetExtension(file).ToLowerInvariant();
return ext == ".jpg" || ext == ".png" || ext == ".gif";
})
.ToArray();

4-3. ファイル名の一部を指定して検索する方法

ファイル名の一部を指定して検索したい場合は、ワイルドカードを使います。

たとえば、reportで始まるファイルを取得する場合は次のようにします。

C#
string[] files = Directory.GetFiles(@"C:\Work", "report*");

backupを含む.zipファイルを取得する場合は、次のように書けます。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*backup*.zip");

2026で終わるファイル名を探したい場合は、次のようにします。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*2026.*");

4-4. ワイルドカードの使い方

Directory.GetFilessearchPatternでは、主に*?のワイルドカードを使います。公式ドキュメントでは、searchPatternにはリテラル文字とワイルドカード文字の組み合わせを指定できる一方、正規表現はサポートされないと説明されています。

*は、0文字以上の任意の文字に一致します。

C#
// すべてのtxtファイル
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

// dataで始まるファイル
string[] files2 = Directory.GetFiles(@"C:\Work", "data*");

// backupを含むファイル
string[] files3 = Directory.GetFiles(@"C:\Work", "*backup*");

?は、任意の1文字に一致します。

C#
// file1.txt, file2.txt などに一致
string[] files = Directory.GetFiles(@"C:\Work", "file?.txt");

注意点として、searchPatternは正規表現ではありません。たとえば、次のような正規表現風の指定はできません。

C#
// 正規表現としては使えない
string[] files = Directory.GetFiles(@"C:\Work", @"data[0-9]+\.csv");

複雑な条件で検索したい場合は、GetFilesで候補を取得してからLINQや正規表現で絞り込みます。

C#
using System.Text.RegularExpressions;

string[] files = Directory.GetFiles(@"C:\Work", "*.csv")
.Where(file => Regex.IsMatch(Path.GetFileName(file), @"^data[0-9]+\.csv$"))
.ToArray();

4-5. 大文字・小文字を考慮した検索の注意点

ファイル検索で大文字・小文字が区別されるかどうかは、実行環境のファイルシステムに依存します。公式ドキュメントでも、pathパラメーターの大文字・小文字の扱いは、コードが実行されているファイルシステムに依存すると説明されています。たとえばWindowsの一般的なNTFS環境とLinux環境では挙動が異なる可能性があります。

実務で大文字・小文字を吸収したい場合は、すべてのファイルを取得してから拡張子を小文字に変換して比較する方法が安全です。

C#
string[] files = Directory.GetFiles(@"C:\Work")
.Where(file => Path.GetExtension(file)
.Equals(".txt", StringComparison.OrdinalIgnoreCase))
.ToArray();

複数拡張子を大文字・小文字を無視して判定する場合は、次のように書けます。

C#
string[] targetExtensions = { ".jpg", ".jpeg", ".png", ".gif" };

string[] files = Directory.GetFiles(@"C:\Images")
.Where(file => targetExtensions.Contains(
Path.GetExtension(file),
StringComparer.OrdinalIgnoreCase))
.ToArray();

5. サブフォルダ内のファイルも取得する方法

5-1. SearchOption.TopDirectoryOnlyの使い方

SearchOption.TopDirectoryOnlyは、指定したフォルダ直下だけを検索するオプションです。

C#
string[] files = Directory.GetFiles(
@"C:\Work",
"*.txt",
SearchOption.TopDirectoryOnly
);

これは、次のコードとほぼ同じ意味です。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

SearchOption.TopDirectoryOnlyを明示しておくと、「サブフォルダは検索しない」という意図がコード上で分かりやすくなります。

5-2. SearchOption.AllDirectoriesの使い方

SearchOption.AllDirectoriesは、指定したフォルダと、その配下にあるすべてのサブフォルダを検索対象にするオプションです。

C#
string[] files = Directory.GetFiles(
@"C:\Work",
"*.txt",
SearchOption.AllDirectories
);

SearchOptionには、現在のディレクトリのみを検索するTopDirectoryOnlyと、現在のディレクトリおよびすべてのサブディレクトリを検索するAllDirectoriesがあります。公式ドキュメントでも、AllDirectoriesは現在のディレクトリとそのすべてのサブディレクトリを検索操作に含める値として説明されています。

5-3. サブフォルダを含めて全ファイルを取得するコード例

サブフォルダを含めて、すべてのファイルを取得するサンプルです。

C#
using System;
using System.IO;

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

string[] files = Directory.GetFiles(
folderPath,
"*",
SearchOption.AllDirectories
);

foreach (string file in files)
{
Console.WriteLine(file);
}

Console.WriteLine($"合計: {files.Length}件");
}
}

すべての.csvファイルをサブフォルダ込みで取得する場合は、次のようにします。

C#
string[] csvFiles = Directory.GetFiles(
@"C:\Work",
"*.csv",
SearchOption.AllDirectories
);

5-4. サブフォルダ検索で発生しやすい例外

SearchOption.AllDirectoriesを使うと、配下のすべてのフォルダをたどります。そのため、次のような例外が発生しやすくなります。

UnauthorizedAccessExceptionは、アクセス権限のないフォルダに入ろうとしたときに発生します。

DirectoryNotFoundExceptionは、検索対象のフォルダが存在しない場合や、途中のパスが無効な場合に発生します。

PathTooLongExceptionは、古い環境や設定によって、パスが長すぎる場合に発生することがあります。

IOExceptionは、パスがファイル名だった場合や、ネットワークエラーなどで発生することがあります。

サブフォルダを含めて検索する場合は、例外処理を入れておくのが安全です。

C#
try
{
string[] files = Directory.GetFiles(
@"C:\Work",
"*",
SearchOption.AllDirectories
);

foreach (string file in files)
{
Console.WriteLine(file);
}
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"アクセス権限がありません: {ex.Message}");
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine($"フォルダが見つかりません: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"入出力エラーが発生しました: {ex.Message}");
}

5-5. アクセス権限がないフォルダを扱うときの注意点

Directory.GetFilesSearchOption.AllDirectoriesを指定した場合、途中にアクセスできないフォルダがあると、そこでUnauthorizedAccessExceptionが発生することがあります。

アクセスできないフォルダを無視して処理したい場合、.NETのバージョンによってはEnumerationOptionsIgnoreInaccessibleを使う方法があります。

C#
var options = new EnumerationOptions
{
RecurseSubdirectories = true,
IgnoreInaccessible = true
};

string[] files = Directory.GetFiles(@"C:\Work", "*", options);

foreach (string file in files)
{
Console.WriteLine(file);
}

ただし、環境によって利用できるAPIが異なる場合があるため、対象の.NETバージョンを確認してください。

古い環境でも安全に処理したい場合は、フォルダを1つずつ再帰的にたどり、アクセスできないフォルダだけをスキップする実装にすると制御しやすくなります。

6. 実用的なファイル取得パターン

6-1. 画像ファイルだけを取得する

画像ファイルだけを取得したい場合は、複数の拡張子を対象にする必要があります。

C#
using System;
using System.IO;
using System.Linq;

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

string[] extensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp" };

string[] imageFiles = Directory.GetFiles(folderPath)
.Where(file => extensions.Contains(
Path.GetExtension(file),
StringComparer.OrdinalIgnoreCase))
.ToArray();

foreach (string file in imageFiles)
{
Console.WriteLine(file);
}
}
}

サブフォルダも含める場合は、次のようにします。

C#
string[] imageFiles = Directory.GetFiles(
folderPath,
"*",
SearchOption.AllDirectories
)
.Where(file => extensions.Contains(
Path.GetExtension(file),
StringComparer.OrdinalIgnoreCase))
.ToArray();

6-2. テキストファイルやCSVファイルを取得する

テキストファイルだけを取得する場合は、*.txtを指定します。

C#
string[] textFiles = Directory.GetFiles(@"C:\Work", "*.txt");

CSVファイルだけを取得する場合は、*.csvを指定します。

C#
string[] csvFiles = Directory.GetFiles(@"C:\Work", "*.csv");

.txt.csvの両方を取得する場合は、LINQで絞り込みます。

C#
string[] files = Directory.GetFiles(@"C:\Work")
.Where(file =>
{
string ext = Path.GetExtension(file);
return ext.Equals(".txt", StringComparison.OrdinalIgnoreCase)
|| ext.Equals(".csv", StringComparison.OrdinalIgnoreCase);
})
.ToArray();

6-3. 更新日時でファイルを絞り込む

更新日時で絞り込む場合は、File.GetLastWriteTimeを使います。

C#
DateTime targetDate = DateTime.Today.AddDays(-7);

string[] recentFiles = Directory.GetFiles(@"C:\Work")
.Where(file => File.GetLastWriteTime(file) >= targetDate)
.ToArray();

foreach (string file in recentFiles)
{
Console.WriteLine($"{file} {File.GetLastWriteTime(file)}");
}

この例では、過去7日以内に更新されたファイルを取得します。

FileInfoを使うと、より読みやすく書けます。

C#
var recentFiles = Directory.GetFiles(@"C:\Work")
.Select(file => new FileInfo(file))
.Where(info => info.LastWriteTime >= DateTime.Today.AddDays(-7))
.ToArray();

foreach (FileInfo file in recentFiles)
{
Console.WriteLine($"{file.FullName} {file.LastWriteTime}");
}

6-4. ファイルサイズで絞り込む

ファイルサイズで絞り込む場合は、FileInfo.Lengthを使います。

C#
long minSize = 1024 * 1024; // 1MB

var largeFiles = Directory.GetFiles(@"C:\Work")
.Select(file => new FileInfo(file))
.Where(info => info.Length >= minSize)
.ToArray();

foreach (FileInfo file in largeFiles)
{
Console.WriteLine($"{file.FullName} {file.Length} bytes");
}

10MB以上のファイルを探す場合は、次のようにします。

C#
long minSize = 10 * 1024 * 1024;

var files = Directory.GetFiles(@"C:\Work")
.Select(file => new FileInfo(file))
.Where(info => info.Length >= minSize)
.ToArray();

6-5. 取得したファイル一覧を並び替える

Directory.GetFilesで返されるファイルの順序は保証されません。公式ドキュメントでも、返されるファイル名の順序は保証されないため、特定の並び順が必要な場合は並べ替えを行う必要があると説明されています。

ファイル名順に並び替える場合は、次のようにします。

C#
string[] files = Directory.GetFiles(@"C:\Work")
.OrderBy(file => Path.GetFileName(file))
.ToArray();

更新日時の新しい順に並び替える場合は、次のようにします。

C#
var files = Directory.GetFiles(@"C:\Work")
.Select(file => new FileInfo(file))
.OrderByDescending(info => info.LastWriteTime)
.ToArray();

ファイルサイズの大きい順に並び替える場合は、次のようにします。

C#
var files = Directory.GetFiles(@"C:\Work")
.Select(file => new FileInfo(file))
.OrderByDescending(info => info.Length)
.ToArray();

6-6. LINQと組み合わせて条件検索する

Directory.GetFilesはLINQと組み合わせることで、柔軟な条件検索ができます。

たとえば、ファイル名にreportを含み、拡張子が.csvで、更新日が30日以内のファイルを取得する場合は次のように書けます。

C#
DateTime fromDate = DateTime.Today.AddDays(-30);

var files = Directory.GetFiles(@"C:\Work", "*.csv")
.Select(file => new FileInfo(file))
.Where(info => info.Name.Contains("report", StringComparison.OrdinalIgnoreCase))
.Where(info => info.LastWriteTime >= fromDate)
.OrderByDescending(info => info.LastWriteTime)
.ToArray();

foreach (FileInfo file in files)
{
Console.WriteLine($"{file.Name} {file.LastWriteTime}");
}

このように、Directory.GetFilesで候補を取得し、LINQで細かい条件を指定するのが実務ではよく使われます。

7. Directory.GetFilesを使うときの注意点

7-1. フォルダが存在しない場合の対処法

存在しないフォルダを指定すると、DirectoryNotFoundExceptionが発生します。事前にDirectory.Existsで存在確認を行うと安全です。

C#
string folderPath = @"C:\Work";

if (Directory.Exists(folderPath))
{
string[] files = Directory.GetFiles(folderPath);

foreach (string file in files)
{
Console.WriteLine(file);
}
}
else
{
Console.WriteLine("フォルダが存在しません。");
}

ただし、存在確認後にフォルダが削除される可能性もあるため、重要な処理ではtry-catchも併用しましょう。

C#
try
{
string[] files = Directory.GetFiles(folderPath);
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("フォルダが見つかりません。");
}

7-2. パスの区切り文字とPath.Combineの使い方

Windowsではパス区切りに\を使いますが、C#の文字列では\はエスケープ文字として扱われます。そのため、通常の文字列で書く場合は\\とします。

C#
string path = "C:\\Work\\Data";

または、逐語的文字列リテラルを使って次のように書けます。

C#
string path = @"C:\Work\Data";

パスを連結する場合は、次のような文字列連結は避けた方が安全です。

C#
string path = basePath + "\\" + folderName;

代わりに、Path.Combineを使います。

C#
string path = Path.Combine(basePath, folderName);

ファイルパスを作る場合も同じです。

C#
string filePath = Path.Combine(@"C:\Work", "data.csv");

7-3. 日本語や空白を含むパスの扱い

Directory.GetFilesは、日本語や空白を含むパスも扱えます。

C#
string folderPath = @"C:\作業フォルダ\テスト データ";

string[] files = Directory.GetFiles(folderPath);

foreach (string file in files)
{
Console.WriteLine(file);
}

注意点は、コマンドライン引数などでパスを受け取る場合です。空白を含むパスは、実行時に引用符で囲まれていないと分割されることがあります。

MyApp.exe "C:\作業フォルダ\テスト データ"

C#側では、受け取った文字列をそのままDirectory.GetFilesに渡せます。

C#
string folderPath = args[0];
string[] files = Directory.GetFiles(folderPath);

7-4. 取得件数が多い場合のメモリ使用量

Directory.GetFilesは、条件に一致するファイルをすべて配列に格納して返します。そのため、対象ファイルが非常に多い場合、メモリ使用量が増える可能性があります。

たとえば、数十万件のファイルを取得する場合は、string[]にすべてのパスが入ります。

C#
string[] files = Directory.GetFiles(
@"C:\HugeFolder",
"*",
SearchOption.AllDirectories
);

取得したファイルを一括で処理する必要がない場合は、Directory.EnumerateFilesを検討しましょう。

C#
foreach (string file in Directory.EnumerateFiles(
@"C:\HugeFolder",
"*",
SearchOption.AllDirectories))
{
Console.WriteLine(file);
}

7-5. 例外処理を入れるべきケース

次のようなケースでは、例外処理を入れるべきです。

ユーザーが指定したフォルダを検索する場合、ネットワークドライブを検索する場合、サブフォルダを含めて検索する場合、アクセス権限が不明なフォルダを検索する場合、大量ファイルを扱う場合などです。

基本的な例外処理の例です。

C#
try
{
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

foreach (string file in files)
{
Console.WriteLine(file);
}
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine($"フォルダが見つかりません: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"アクセス権限がありません: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"I/Oエラーが発生しました: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"予期しないエラーが発生しました: {ex.Message}");
}

8. Directory.GetFilesでよくあるエラーと解決方法

8-1. DirectoryNotFoundExceptionの原因と対処法

DirectoryNotFoundExceptionは、指定したフォルダが存在しない場合や、パスが無効な場合に発生します。公式ドキュメントでも、指定されたパスが見つからない、または無効な場合に発生する例外として説明されています。

原因の例です。

C#
string[] files = Directory.GetFiles(@"C:\NotExists");

対処法としては、事前にDirectory.Existsで確認します。

C#
string folderPath = @"C:\NotExists";

if (!Directory.Exists(folderPath))
{
Console.WriteLine("指定されたフォルダは存在しません。");
return;
}

string[] files = Directory.GetFiles(folderPath);

8-2. UnauthorizedAccessExceptionの原因と対処法

UnauthorizedAccessExceptionは、アクセス権限がないフォルダやファイルにアクセスしようとした場合に発生します。

たとえば、管理者権限が必要なフォルダや、他ユーザー専用のフォルダ、システムフォルダなどを検索した場合に発生することがあります。

C#
try
{
string[] files = Directory.GetFiles(
@"C:\System Volume Information",
"*",
SearchOption.AllDirectories
);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("アクセス権限がありません。");
}

対処法としては、アクセス可能なフォルダだけを対象にする、管理者権限で実行する、try-catchでスキップする、EnumerationOptions.IgnoreInaccessibleを検討する、などがあります。

8-3. IOExceptionの原因と対処法

IOExceptionは、入出力処理に関するエラーで発生します。

Directory.GetFilesでは、指定したpathがフォルダではなくファイルだった場合や、ネットワークエラーが発生した場合などに起こる可能性があります。公式ドキュメントでも、pathがファイル名の場合やネットワークエラーが発生した場合にIOExceptionが発生すると説明されています。

対処法としては、Directory.Existsでフォルダかどうかを確認します。

C#
string path = @"C:\Work\data.txt";

if (!Directory.Exists(path))
{
Console.WriteLine("指定されたパスはフォルダではありません。");
return;
}

string[] files = Directory.GetFiles(path);

8-4. ArgumentExceptionやArgumentNullExceptionの原因

ArgumentNullExceptionは、pathsearchPatternnullを渡した場合に発生します。

C#
string folderPath = null;

string[] files = Directory.GetFiles(folderPath);

対処法は、事前にstring.IsNullOrWhiteSpaceなどで確認することです。

C#
if (string.IsNullOrWhiteSpace(folderPath))
{
Console.WriteLine("フォルダパスが指定されていません。");
return;
}

ArgumentExceptionは、古い.NET Frameworkや.NET Core環境で無効な文字を含むパスを指定した場合、または無効な検索パターンを指定した場合などに発生することがあります。

C#
string searchPattern = "..\\"; // 不正なパターンになる可能性がある

ユーザー入力をそのまま検索パターンに使う場合は、入力値を検証しましょう。

8-5. エラーを防ぐ安全なコード例

実務で使いやすい、安全なファイル取得コードの例です。

C#
using System;
using System.IO;

class Program
{
static void Main()
{
string folderPath = @"C:\Work";
string searchPattern = "*.txt";

if (string.IsNullOrWhiteSpace(folderPath))
{
Console.WriteLine("フォルダパスが空です。");
return;
}

if (!Directory.Exists(folderPath))
{
Console.WriteLine("指定されたフォルダが存在しません。");
return;
}

try
{
string[] files = Directory.GetFiles(
folderPath,
searchPattern,
SearchOption.TopDirectoryOnly
);

foreach (string file in files)
{
Console.WriteLine(file);
}

Console.WriteLine($"取得件数: {files.Length}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"アクセス権限がありません: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"入出力エラーが発生しました: {ex.Message}");
}
catch (ArgumentException ex)
{
Console.WriteLine($"引数が不正です: {ex.Message}");
}
}
}

9. Directory.GetFilesとEnumerateFilesの使い分け

9-1. GetFilesが向いているケース

Directory.GetFilesが向いているのは、取得件数が比較的少なく、ファイル一覧を配列としてまとめて扱いたい場合です。

たとえば、フォルダ直下の設定ファイルを取得する場合、数十件程度のCSVファイルを読み込む場合、画面にファイル一覧を表示する場合などです。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*.csv");

Console.WriteLine($"CSVファイル数: {files.Length}");

Lengthで件数をすぐに取得できる点も、GetFilesの分かりやすいメリットです。

9-2. EnumerateFilesが向いているケース

Directory.EnumerateFilesが向いているのは、大量のファイルを1件ずつ処理したい場合です。

C#
foreach (string file in Directory.EnumerateFiles(
@"C:\Logs",
"*.log",
SearchOption.AllDirectories))
{
Console.WriteLine(file);
}

このように書くと、すべてのファイルを配列に格納してから処理するのではなく、列挙しながら順番に処理できます。

特に、ログ解析、バックアップ、ファイル変換、一括削除など、大量ファイルを順次処理する場合に向いています。

9-3. 大量ファイルを扱う場合のパフォーマンス比較

大量ファイルを扱う場合、GetFilesは最初にすべての結果を配列として作成します。そのため、最初の1件を処理するまでに時間がかかり、メモリ使用量も増えます。

一方、EnumerateFilesは列挙しながら処理できるため、最初の1件を早く処理でき、メモリ効率も良くなります。公式ドキュメントでも、多くのファイルやディレクトリを操作する場合はEnumerateFilesの方が効率的と説明されています。

ただし、処理対象が少ない場合は、体感できる差はほとんどないことも多いです。コードの単純さを優先するならGetFiles、大量ファイルや逐次処理を重視するならEnumerateFilesを選ぶとよいでしょう。

9-4. 実務での使い分けの目安

実務では、次のように使い分けると分かりやすいです。

小規模なフォルダを対象にして、ファイル一覧をまとめて使うならDirectory.GetFilesが便利です。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

大量ファイルを1件ずつ処理するならDirectory.EnumerateFilesが向いています。

C#
foreach (string file in Directory.EnumerateFiles(@"C:\Work", "*.txt"))
{
// 1件ずつ処理
}

更新日時やファイルサイズなどで絞り込みたい場合は、どちらもLINQと組み合わせられます。ただし、大量ファイルではEnumerateFilesを使う方が効率的です。

C#
var files = Directory.EnumerateFiles(@"C:\Work", "*.log")
.Where(file => File.GetLastWriteTime(file) >= DateTime.Today.AddDays(-7));

foreach (string file in files)
{
Console.WriteLine(file);
}

10. Directory.GetFilesのサンプルコード集

10-1. フォルダ内の全ファイルを取得するサンプル

C#
using System;
using System.IO;

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

string[] files = Directory.GetFiles(folderPath);

foreach (string file in files)
{
Console.WriteLine(file);
}
}
}

ファイル名だけを表示する場合です。

C#
foreach (string file in files)
{
Console.WriteLine(Path.GetFileName(file));
}

10-2. 指定拡張子のファイルを取得するサンプル

C#
using System;
using System.IO;

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

string[] csvFiles = Directory.GetFiles(folderPath, "*.csv");

foreach (string file in csvFiles)
{
Console.WriteLine(file);
}

Console.WriteLine($"CSVファイル数: {csvFiles.Length}");
}
}

.txtファイルを取得する場合です。

C#
string[] textFiles = Directory.GetFiles(@"C:\Work", "*.txt");

10-3. サブフォルダを含めて検索するサンプル

C#
using System;
using System.IO;

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

string[] files = Directory.GetFiles(
folderPath,
"*",
SearchOption.AllDirectories
);

foreach (string file in files)
{
Console.WriteLine(file);
}

Console.WriteLine($"合計: {files.Length}件");
}
}

サブフォルダを含めて.logファイルを検索する場合です。

C#
string[] logFiles = Directory.GetFiles(
@"C:\Logs",
"*.log",
SearchOption.AllDirectories
);

10-4. 複数条件でファイルを絞り込むサンプル

拡張子、ファイル名、更新日時を条件に絞り込むサンプルです。

C#
using System;
using System.IO;
using System.Linq;

class Program
{
static void Main()
{
string folderPath = @"C:\Work";
DateTime fromDate = DateTime.Today.AddDays(-30);

var files = Directory.GetFiles(folderPath, "*.csv")
.Select(file => new FileInfo(file))
.Where(info => info.Name.Contains("report", StringComparison.OrdinalIgnoreCase))
.Where(info => info.LastWriteTime >= fromDate)
.OrderByDescending(info => info.LastWriteTime)
.ToArray();

foreach (FileInfo file in files)
{
Console.WriteLine($"{file.Name} {file.LastWriteTime}");
}
}
}

複数拡張子を対象にするサンプルです。

C#
string[] extensions = { ".txt", ".csv", ".log" };

string[] files = Directory.GetFiles(@"C:\Work")
.Where(file => extensions.Contains(
Path.GetExtension(file),
StringComparer.OrdinalIgnoreCase))
.ToArray();

10-5. 例外処理を含めた実用サンプル

C#
using System;
using System.IO;
using System.Linq;

class Program
{
static void Main()
{
string folderPath = @"C:\Work";
string searchPattern = "*.txt";

try
{
if (!Directory.Exists(folderPath))
{
Console.WriteLine("指定されたフォルダが存在しません。");
return;
}

string[] files = Directory.GetFiles(
folderPath,
searchPattern,
SearchOption.TopDirectoryOnly
);

var sortedFiles = files
.Select(file => new FileInfo(file))
.OrderByDescending(info => info.LastWriteTime)
.ToArray();

foreach (FileInfo file in sortedFiles)
{
Console.WriteLine($"{file.Name} {file.LastWriteTime}");
}

Console.WriteLine($"取得件数: {sortedFiles.Length}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"アクセス権限がありません: {ex.Message}");
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine($"フォルダが見つかりません: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"入出力エラーが発生しました: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"予期しないエラーが発生しました: {ex.Message}");
}
}
}

11. Directory.GetFilesに関するよくある質問

11-1. Directory.GetFilesでフォルダは取得できる?

Directory.GetFilesで取得できるのはファイルです。フォルダは取得できません。

フォルダ一覧を取得したい場合は、Directory.GetDirectoriesを使います。

C#
string[] directories = Directory.GetDirectories(@"C:\Work");

foreach (string dir in directories)
{
Console.WriteLine(dir);
}

ファイルとフォルダの両方を処理したい場合は、GetFilesGetDirectoriesを組み合わせます。

C#
string[] files = Directory.GetFiles(@"C:\Work");
string[] directories = Directory.GetDirectories(@"C:\Work");

11-2. 複数の拡張子を一度に指定できる?

Directory.GetFilessearchPatternに、複数の拡張子を一度にOR条件で指定することはできません。

たとえば、次のような指定はできません。

C#
// このような指定は不可
Directory.GetFiles(@"C:\Work", "*.txt;*.csv");

複数拡張子を扱う場合は、拡張子ごとにGetFilesを実行するか、すべてのファイルを取得してからLINQで絞り込みます。

C#
string[] extensions = { ".txt", ".csv" };

string[] files = Directory.GetFiles(@"C:\Work")
.Where(file => extensions.Contains(
Path.GetExtension(file),
StringComparer.OrdinalIgnoreCase))
.ToArray();

11-3. ファイル名だけを取得するには?

Path.GetFileNameを使います。

C#
string[] files = Directory.GetFiles(@"C:\Work");

foreach (string file in files)
{
Console.WriteLine(Path.GetFileName(file));
}

拡張子なしのファイル名だけが欲しい場合は、Path.GetFileNameWithoutExtensionを使います。

C#
string name = Path.GetFileNameWithoutExtension(file);

11-4. サブフォルダ検索でアクセス拒否された場合は?

SearchOption.AllDirectoriesでサブフォルダを検索していると、アクセス権限のないフォルダでUnauthorizedAccessExceptionが発生することがあります。

基本的には、try-catchで例外を処理します。

C#
try
{
string[] files = Directory.GetFiles(
@"C:\Work",
"*",
SearchOption.AllDirectories
);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("アクセスできないフォルダがあります。");
}

アクセスできないフォルダをスキップしたい場合は、EnumerationOptionsIgnoreInaccessibleを検討します。

C#
var options = new EnumerationOptions
{
RecurseSubdirectories = true,
IgnoreInaccessible = true
};

string[] files = Directory.GetFiles(@"C:\Work", "*", options);

11-5. GetFilesとEnumerateFilesはどちらを使うべき?

少数のファイルをまとめて取得するなら、Directory.GetFilesで問題ありません。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

大量のファイルを1件ずつ処理するなら、Directory.EnumerateFilesがおすすめです。

C#
foreach (string file in Directory.EnumerateFiles(@"C:\Work", "*.txt"))
{
Console.WriteLine(file);
}

目安として、ファイル一覧を配列として一括で使いたいならGetFiles、メモリ効率を重視して順次処理したいならEnumerateFilesを使うとよいでしょう。

まとめ

Directory.GetFilesは、C#でフォルダ内のファイル一覧を取得するための基本的なメソッドです。指定したフォルダ直下のファイルを取得するだけでなく、searchPatternを使って拡張子やファイル名で絞り込んだり、SearchOption.AllDirectoriesを使ってサブフォルダ内のファイルまで検索したりできます。

基本形は次のとおりです。

C#
string[] files = Directory.GetFiles(@"C:\Work");

拡張子で絞り込む場合は、次のようにします。

C#
string[] files = Directory.GetFiles(@"C:\Work", "*.txt");

サブフォルダも含める場合は、次のようにします。

C#
string[] files = Directory.GetFiles(
@"C:\Work",
"*.txt",
SearchOption.AllDirectories
);

ただし、Directory.GetFilesは結果をすべて配列として返すため、大量ファイルを扱う場合はメモリ使用量に注意が必要です。そのような場合は、Directory.EnumerateFilesを使うと効率的に処理できます。

また、フォルダが存在しない場合、アクセス権限がない場合、パスが不正な場合などには例外が発生する可能性があります。実務では、Directory.Existsによる存在確認やtry-catchによる例外処理を入れて、安全にファイル検索を行いましょう。