Directory.Exists() / Directory.CreateDirectory()
| 対応: | C# 1.0(2002) |
|---|
ディレクトリの存在確認・作成・削除・ファイル一覧取得など、ディレクトリを操作する『Directory』クラスのメソッドの使い方です。
構文
using System.IO; // ディレクトリが存在するか確認します。 bool exists = Directory.Exists(string path); // ディレクトリを作成します(途中のディレクトリも再帰的に作成します)。 Directory.CreateDirectory(string path); // ディレクトリを削除します。 Directory.Delete(string path); // ディレクトリを再帰的に削除します(中身ごと削除)。 Directory.Delete(string path, bool recursive); // ディレクトリ内のファイルパス一覧を取得します。 string[] files = Directory.GetFiles(string path); string[] files = Directory.GetFiles(string path, string searchPattern); // サブディレクトリのパス一覧を取得します。 string[] dirs = Directory.GetDirectories(string path); // ディレクトリを移動(リネーム)します。 Directory.Move(string sourceDirName, string destDirName);
メソッド一覧
| メソッド | 概要 |
|---|---|
| Directory.Exists(path) | 指定したパスのディレクトリが存在すれば true を返します。 |
| Directory.CreateDirectory(path) | ディレクトリを作成します。途中のパスが存在しない場合も含めて再帰的に作成します。既存の場合は何もしません。 |
| Directory.Delete(path) | 空のディレクトリを削除します。中身がある場合は IOException をスローします。 |
| Directory.Delete(path, true) | ディレクトリを中身ごと再帰的に削除します。 |
| Directory.GetFiles(path) | ディレクトリ内のファイルのフルパス一覧を string 配列で返します。 |
| Directory.GetFiles(path, pattern) | "*.txt" などのパターンで絞り込んでファイル一覧を返します。 |
| Directory.GetDirectories(path) | ディレクトリ内のサブディレクトリのフルパス一覧を返します。 |
| Directory.Move(src, dest) | ディレクトリを別の場所へ移動します。リネームにも使用できます。 |
サンプルコード
Program.cs
using System;
using System.IO;
string basePath = "work";
string subPath = Path.Combine(basePath, "logs", "2024");
// Directory.Exists() でディレクトリの存在を確認します。
Console.WriteLine(Directory.Exists(basePath)); // False
// Directory.CreateDirectory() でディレクトリを作成します。
// 中間のパス(logs/2024)も含めて一度に作成できます。
Directory.CreateDirectory(subPath);
Console.WriteLine(Directory.Exists(subPath)); // True
// テスト用ファイルを作成します。
File.WriteAllText(Path.Combine(subPath, "app.log"), "アプリログ");
File.WriteAllText(Path.Combine(subPath, "error.log"), "エラーログ");
File.WriteAllText(Path.Combine(subPath, "data.txt"), "データファイル");
// Directory.GetFiles() でファイル一覧を取得します。
Console.WriteLine("--- すべてのファイル ---");
foreach (string file in Directory.GetFiles(subPath))
{
Console.WriteLine(Path.GetFileName(file));
}
// パターンで絞り込みます(*.log のみ)。
Console.WriteLine("--- .log ファイルのみ ---");
foreach (string file in Directory.GetFiles(subPath, "*.log"))
{
Console.WriteLine(Path.GetFileName(file));
}
// Directory.GetDirectories() でサブディレクトリ一覧を取得します。
Console.WriteLine("--- サブディレクトリ ---");
foreach (string dir in Directory.GetDirectories(basePath))
{
Console.WriteLine(Path.GetFileName(dir));
}
// Directory.Delete() で中身ごと再帰削除します。
Directory.Delete(basePath, recursive: true);
Console.WriteLine($"削除後: {Directory.Exists(basePath)}"); // False
コンパイルして実行すると次のようになります。
dotnet script directory_exists_createdirectory.csx False True --- すべてのファイル --- app.log data.txt error.log --- .log ファイルのみ --- app.log error.log --- サブディレクトリ --- logs 削除後: False
実践パターン: 再帰的なファイル検索
SearchOption.AllDirectories を使うと、サブディレクトリも含めた全ファイルを一括で取得できます。
RecursiveSearch.cs
using System;
using System.IO;
// テスト用のディレクトリ構造を作成します。
Directory.CreateDirectory("project/src");
Directory.CreateDirectory("project/assets");
File.WriteAllText("project/src/main.cs", "// main");
File.WriteAllText("project/src/helper.cs", "// helper");
File.WriteAllText("project/assets/icon.png", "png data");
File.WriteAllText("project/readme.txt", "README");
// SearchOption.TopDirectoryOnly(デフォルト): 直下のファイルのみ
Console.WriteLine("--- TopDirectoryOnly ---");
foreach (string f in Directory.GetFiles("project", "*", SearchOption.TopDirectoryOnly))
Console.WriteLine(Path.GetFileName(f));
// SearchOption.AllDirectories: サブディレクトリも含む
Console.WriteLine("--- AllDirectories ---");
foreach (string f in Directory.GetFiles("project", "*", SearchOption.AllDirectories))
Console.WriteLine(Path.GetRelativePath("project", f));
// .cs ファイルだけを再帰的に収集します。
Console.WriteLine("--- .cs ファイル ---");
foreach (string f in Directory.GetFiles("project", "*.cs", SearchOption.AllDirectories))
Console.WriteLine(Path.GetFileName(f));
// 後片付けします。
Directory.Delete("project", recursive: true);
コンパイルして実行すると次のようになります。
dotnet script recursive_search.csx --- TopDirectoryOnly --- readme.txt --- AllDirectories --- readme.txt src/main.cs src/helper.cs assets/icon.png --- .cs ファイル --- main.cs helper.cs
実践パターン: バックアップディレクトリの管理
日付付きのバックアップディレクトリを作成し、古いバックアップを自動削除するパターンです。
BackupManager.cs
using System;
using System.IO;
using System.Linq;
string backupRoot = "backups";
Directory.CreateDirectory(backupRoot);
// 今日のバックアップディレクトリを作成します。
string todayDir = Path.Combine(backupRoot, DateTime.Today.ToString("yyyyMMdd"));
Directory.CreateDirectory(todayDir);
File.WriteAllText(Path.Combine(todayDir, "data.bak"), "backup data");
Console.WriteLine($"バックアップ作成: {todayDir}");
// 古いバックアップ(7日以上前)を削除します。
string[] dirs = Directory.GetDirectories(backupRoot);
foreach (string dir in dirs)
{
string dirName = Path.GetFileName(dir);
if (DateTime.TryParseExact(dirName, "yyyyMMdd",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None, out DateTime dirDate))
{
int age = (DateTime.Today - dirDate).Days;
if (age >= 7)
{
Directory.Delete(dir, recursive: true);
Console.WriteLine($"削除: {dirName}({age}日前)");
}
else
{
Console.WriteLine($"保持: {dirName}({age}日前)");
}
}
}
// 後片付けします。
Directory.Delete(backupRoot, recursive: true);
コンパイルして実行すると次のようになります。
dotnet script backup_manager.csx バックアップ作成: backups/20240115 保持: 20240115(0日前)
よくあるミス
よくあるミス1: 空でないディレクトリを Delete() しようとする
『Directory.Delete(path)』は空のディレクトリにしか使えません。中身があると IOException がスローされます。
using System;
using System.IO;
Directory.CreateDirectory("testdir");
File.WriteAllText("testdir/file.txt", "data");
// NG: 中身があると IOException が発生します。
Directory.Delete("testdir");
修正後は次の通りです。
dotnet run Unhandled exception. System.IO.IOException: The directory is not empty. : 'testdir'
修正後は次の通りです。
using System;
using System.IO;
Directory.CreateDirectory("testdir");
File.WriteAllText("testdir/file.txt", "data");
// OK: recursive: true で中身ごと削除します。
Directory.Delete("testdir", recursive: true);
Console.WriteLine("削除完了");
修正後は次の通りです。
dotnet run 削除完了
よくあるミス2: パス文字列を手動で結合する
文字列連結でパスを組み立てると、OS によってパス区切り文字が異なりエラーが起きます。必ず Path.Combine() を使います。
using System;
using System.IO;
// NG: Windows では \、Linux/Mac では / が必要なため、手動結合はエラーの原因になります。
string bad = "work" + "/" + "logs"; // macOS では動くが Windows では意図しない動作になる場合があります。
// OK: Path.Combine() は OS の区切り文字を自動補完します。
string good = Path.Combine("work", "logs");
Console.WriteLine(good); // Windows: work\logs / macOS: work/logs
概要
『Directory.CreateDirectory()』はディレクトリが既に存在していても例外をスローしないため、Exists() で事前確認しなくても安全に使えます。『Directory.Delete(path, true)』で再帰削除を行うと元に戻せないため、パスを十分確認してから実行してください。
パス文字列の組み立てには OS ごとの区切り文字の差異を吸収するPath.Combine() / Path.GetFileName()の使用を推奨します。ファイルの読み書きについてはFile.ReadAllText() / WriteAllText()をご確認ください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。