Directory

作成

メソッド 機能
CreateDirectory(String) 指定のディレクトリが存在していないならば、サブディレクトリも含めて作成する。さもなくば何もしない
CreateDirectory(String, DirectorySecurity) 指定のセキュリティでディレクトリを作成する。
オーバーロード - Directory.CreateDirectory Method (System.IO) | Microsoft Learn

CreateDirectory(String)

public static DirectoryInfo CreateDirectory(string path)
Directory.CreateDirectory メソッド (String) (System.IO) | MSDN

pathにはディレクトリのパスを指定します。これをファイルのパスとすると、それがディレクトリ名と解釈されて作成されます。つまり"c:\dir\sample.txt"と指定すると、c:\dirにsample.txtの名前のディレクトリが作成されます。これを適切に処理するには、Path.GetDirectoryName()でディレクトリ名の部分のみを取得してから渡すようにします。

Directory.CreateDirectory(Path.GetDirectoryName(path));
  • ディレクトリがシンボリックリンクだと、DirectoryNotFoundExceptionが投げられる
  • 権限がないと、UnauthorizedAccessExceptionが投げられる

コピー

ディレクトリをコピーするメソッドは提供されていないため、同名のディレクトリを作成した上で、それに含まれるファイルを1つずつコピーします。例 - DirectoryInfo クラス (System.IO) | Microsoft Learn

移動

public static void Move (
    string sourceDirName,
    string destDirName
    );
Directory.Move(String, String) メソッド (System.IO) | Microsoft Learn

異なる名前で同じディレクトリへ移動することで、ディレクトリ名の変更 (rename) として機能させられます。

削除

Delete()で削除できます。

public static void Delete(
    string path
)
  • ディレクトリが存在しないとDirectoryNotFoundExceptionが投げられる。
  • ディレクトリに読み取り専用のファイルが含まれているとUnauthorizedAccessExceptionが投げられディレクトリの削除に失敗するが、読み取り専用ではないファイルは削除される。

ディレクトリが空ではない場合には次のオーバーロードでrecursiveをtrueとしなければ、「ディレクトリが空ではありません。(The directory is not empty.)」としてSystem.IO.IOExceptionが投げられます。ただしrecursiveをtrueとしても、この例外が投げられることがあります。

public static void Delete(
    string path,
    bool recursive
)
Directory.Delete メソッド (System.IO) | Microsoft Learn
  • ディレクトリ内のファイルが使用中だと「別のプロセスで使用されているため、プロセスはファイル '***' にアクセスできません。」としてIOExceptionが投げられる。
  • ディレクトリ内のファイルの状況によっては「パス '***' の一部が見つかりませんでした。(Could not find a part of the path '***'.)」として、そのファイル名でDirectoryNotFoundExceptionが投げられる。

recursiveをtrueとするとサブディレクトリがあるときに再帰的に削除メソッドが呼び出されるため、処理に時間がかかることがあります。

ディレクトリが空であるかは、EnumerateFileSystemEntries()で取得できる列挙子を進めることで効率的に確認できます。io - How to quickly check if folder is empty (.NET)? - Stack Overflow

bool empty = !Directory.EnumerateFileSystemEntries(path).Any();

存在確認

Exists()

public static bool Exists (string path);
Directory.Exists(String) Method (System.IO) | Microsoft Learn

指定ディレクトリが存在しているならば、trueが返されます。次のような場合はfalseとなります。

  • ディレクトリが存在しない
  • 指定されたのがディレクトリではない
  • 確認時に次のような理由によりエラーが発生した
    • ファイル名に無効な文字が含まれている
    • ファイル名が長すぎる
    • ディスクの障害または喪失
    • ファイルの読み取り権限がない
Exists - directory.cs

確認前に末尾の空白は削除されます。大文字/小文字は区別されません。

string path = @"C:\dir\sample.txt";

bool result1 = Directory.Exists(path);                        // false
bool result2 = Directory.Exists(Path.GetDirectoryName(path)); // true

bool result3 = Directory.Exists("sample.txt");                // false

ディレクトリ内のファイル名などの取得

// ファイル名
string[] files1 = Directory.GetFiles(path);
string[] files2 = Directory.GetFiles(path, "*.txt"); // パターンに一致するもののみ
string[] files3 = Directory.GetFiles(path, "*.txt"
    , SearchOption.AllDirectories); // サブディレクトリも含める

// サブディレクトリ名
string[] directories = Directory.GetDirectories(path);

// ファイル名とサブディレクトリ名
string[] fileSystemEntries = Directory.GetFileSystemEntries(path);
メソッド 機能
GetFiles(String) ディレクトリ内のすべてのファイル名を取得できる
GetDirectories(String) ディレクトリ内のすべてのサブディレクトリ名を取得できる
GetFileSystemEntries(String) ディレクトリ内のすべてのファイル名とサブディレクトリ名を取得できる

これらのメソッドからは、パスを含むフルネーム (full name) で返されます。これをパスを除いた名前で取得するには、DirectoryInfo.GetFiles()などでFileInfoクラスなどで得て、そのNameプロパティから取得します。

ディレクトリを相対パスで指定したときは結果も相対パスで、絶対パスならば結果も絶対パスで返されます。

GetFiles()

public static string[] GetFiles (
    string path,
    string searchPattern,
    System.IO.SearchOption searchOption
    );
GetFiles(String, String, SearchOption) - Directory.GetFiles メソッド (System.IO) | Microsoft Learn

pathの大文字/小文字は、NTFSでは区別されませんが、Linuxのファイルシステムでは区別されます。

searchPatternの大文字/小文字は、区別されません。「*」と「?」のワイルドカードを指定できます。

searchPatternsearchOptionを省略したときは、それぞれ"*"、SearchOption.TopDirectoryOnlyが指定されます。GetFiles - directory.cs

EnumerateFiles()

.NET 4.0以降ならば、より効率的にファイル名などを取得できるEnumerateFiles()などを用います。

メソッド 機能
EnumerateFiles(String) ディレクトリ内のすべてのファイル名の、コレクションを取得できる
EnumerateDirectories(String) ディレクトリ内のすべてのサブディレクトリ名の、コレクションを取得できる
EnumerateFileSystemEntries(String) ディレクトリ内のすべてのファイル名とサブディレクトリ名の、コレクションを取得できる

またGetFiles()などで指定できるパターンは単純なものに限られるため、より複雑な条件はEnumerateFiles()などでコレクションとして取得した上で処理します。c# - Can you call Directory.GetFiles() with multiple filters? - Stack Overflow

public static System.Collections.Generic.IEnumerable<string> EnumerateFiles (
    string path,
    string searchPattern,
    System.IO.SearchOption searchOption
    );
EnumerateFiles(String, String, SearchOption) - Directory.EnumerateFiles メソッド (System.IO) | Microsoft Learn

戻り値はIEnumerable<string>で返されるため、そのままLINQのデータソースとして渡せます。

IEnumerable<string> files
    = from file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
    where file.EndsWith(".txt") || file.EndsWith(".ini")
    select file;

また、foreachでそのまま列挙できます。

foreach (string file in Directory.EnumerateFiles(path))
{
}

ただし列挙操作中にアクセス権のないファイルがあると、そこでUnauthorizedAccessExceptionが投げられ処理が停止してしまいます。これを回避するには列挙子を進めるときに例外を捕捉し、対処するようにします。

IEnumerable<string> files = Directory.EnumerateFiles(path);
using (IEnumerator<string> iterator = files.GetEnumerator())
{
    while (true)
    {
        try
        {
            if (!iterator.MoveNext()) break;
        }
        catch (UnauthorizedAccessException)
        {
            continue;
        }

        string file = iterator.Current;
    }
}

作業ディレクトリ (working directory)

public static string GetCurrentDirectory()
Directory.GetCurrentDirectory メソッド (System.IO) | MSDN
public static void SetCurrentDirectory( string path )
Directory.SetCurrentDirectory メソッド (String) (System.IO) | MSDN

現在の作業ディレクトリ (current working directory) の取得と設定を行えます。これはEnvironment.CurrentDirectoryプロパティへの読み書きでも可能ですが、このプロパティは内部ではDirectoryクラスのメソッドを呼んでいるだけです。CurrentDirectory - environment.cs

設定時には、末尾の空白とバックスラッシュは削除されます。

Directory.SetCurrentDirectory("C:\\dir");
string dir1 = Directory.GetCurrentDirectory(); // "C:\\dir"

Directory.SetCurrentDirectory("C:\\dir ");
string dir2 = Directory.GetCurrentDirectory(); // "C:\\dir"

Directory.SetCurrentDirectory("C:\\dir\\");
string dir3 = Directory.GetCurrentDirectory(); // "C:\\dir"

なおVisual Studioでのデバッグ時に設定するだけならば、プロジェクトのプロパティを開き[デバッグ]タブの[作業ディレクトリ]でも設定できます。ただしこの設定は、単体テストのデバッグには適用されません。C# デバッグ構成のプロジェクト設定 | MSDN

作業ディレクトリは、FileDialogによって変更されることがあります。

C++での作業ディレクトリへのアクセス

アプリケーションのディレクトリ

AppDomain.CurrentDomain.BaseDirectoryから得られます。c# - Best way to get application folder path - Stack Overflow

またはAssembly.Locationからアプリケーションの実行ファイルのパスを取得し、そのディレクトリ名の部分を取得することでも得られます。c# - How can I get the application's path in a .NET console application? - Stack Overflow

System.Reflection.Assembly assembly = typeof(MyProgram).Assembly;
string directory = Path.GetDirectoryName(assembly.Location);

Application.StartupPathからでも得られますが、Visual Studioのテスト環境ではC:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindowのようなディレクトリが返されます。

指定パスがディレクトリかどうかの判別

File.Exists()で真ならばファイル、Directory.Exists()で真ならばディレクトリです。File.Exists メソッド (String) (System.IO) | MSDN

if(File.Exists(path))
{
    // pathはファイル
}
else if(Directory.Exists(path))
{
    // pathはディレクトリ
}
else
{
    // pathはファイルでもディレクトリでもない
}
Directory.Exists メソッド (String) (System.IO) | MSDN

なお属性から調べる方法もありますが、この方法では指定のパスが存在しないときにはFileNotFoundExceptionが、ネットワークドライブが存在しないときにはIOExceptionが投げられます。How do I distinguish a file or a folder in a drag and drop event in c#? - Stack Overflow

FileAttributes attributes = File.GetAttributes(path);
bool isDirectory = attributes.HasFlag(FileAttributes.Directory);

このときFileInfo.Attributesプロパティから属性を取得しないようにします。このプロパティはパスが存在しないときは-1を返すため、ファイルでもディレクトリでもないときにHasFlag(FileAttributes.Directory)がtrueとなります。

Directory.Exists()も内部では属性で判定しているため、効率を追求するならば、こちらの方法を用います。

Microsoft Learnから検索