C Sharpの基礎 - ディレクトリ

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動

概要

C#におけるディレクトリ操作は、System.IO名前空間に含まれるDirectoryクラスとDirectoryInfoクラスを使用して行う。
これらのクラスを使用することにより、ファイルシステム上のディレクトリに関する様々な操作や情報取得が可能になる。

Directoryクラスは静的メソッドを提供しており、特定のディレクトリインスタンスを作成せずにディレクトリ操作を行うことができる。
一方、DirectoryInfoクラスはオブジェクト指向のアプローチを取り、特定のディレクトリに対して複数の操作を行う場合に有効である。

  • ディレクトリの作成
    Directory.CreateDirectoryメソッドを使用する。
    このメソッドは指定されたパスにディレクトリが存在しない場合、そのディレクトリを作成する。
    既に存在する場合は何も行わず、エラーも発生しない。

  • ディレクトリの削除
    Directory.Deleteメソッドを使用する。
    ただし、空でないディレクトリを削除しようとすると例外が発生するため、注意が必要である。
    再帰的に削除する場合は、オーバーロードされたメソッドを使用する。

  • ディレクトリの存在確認
    Directory.Existsメソッドを使用する。
    このメソッドは指定されたパスにディレクトリが存在するかどうかをブール値で返す。

  • ディレクトリの移動や名前変更
    Directory.Moveメソッドを使用する。
    このメソッドは、ソースパスとデスティネーションパスを引数に取る。


ディレクトリ内のファイルやサブディレクトリの列挙には、以下に示すメソッドを使用する。
これらのメソッドは、検索パターンや検索オプションを指定することにより、柔軟な検索が可能である。

  • Directory.GetFilesメソッド
  • Directory.GetDirectoriesメソッド
  • Directory.GetFileSystemEntriesメソッド


DirectoryInfoクラスを使用する場合、まずインスタンスを生成して、そのインスタンスに対してメソッドを呼び出す。
例えば、DirectoryInfo di = new DirectoryInfo(@"/home/user/hoge"); のようにインスタンスを生成して、Createメソッド、Deleteメソッド、MoveToメソッド等を使用する。

ディレクトリのセキュリティ設定や属性の取得・設定も可能である。
Directory.GetAccessControlメソッドやDirectoryInfo.Attributesプロパティを使用することにより、これらの情報にアクセスすることができる。

C#でのディレクトリ操作は、エラー処理が重要となる。
ファイルシステムへのアクセスはI/O操作を伴うため、IOExceptionやUnauthorizedAccessException等の例外が発生する可能性があるため、
適切なtry-catchブロックを使用して、これらの例外を処理することが推奨される。

また、.NET Coreや.NET 5以降では、クロスプラットフォームの開発がサポートされているため、パス区切り文字等の違いに注意が必要である。
Path.DirectorySeparatorCharを使用することにより、プラットフォーム間の互換性を保つことができる。

ディレクトリ操作を行う場合は、パフォーマンスにも注意が必要となる。
大量のファイルやディレクトリを扱う場合、非同期メソッドの使用や並列処理を検討することにより、アプリケーションの応答性を向上させることができる。


ディレクトリの作成

ディレクトリの作成は高速であるため、非同期処理は必要ない。
ただし、ネットワークドライブ上での操作等、遅延が予想される特殊なケースでは、Directory.CreateDirectoryAsyncメソッド (.NET 6以降で使用可能) を推奨する。

新規作成

以下の例では、ディレクトリを新規作成している。
ただし、既存のディレクトリがある場合は何もしない。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user/newDirectory";
 
       // ディレクトリを作成
       Directory.CreateDirectory(path);
    }
 }


既存のディレクトリを確認してから新規作成

既存ディレクトリを確認する方法は、不要な処理を避ける場合に有効である。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user/newDirectory";
 
       // ディレクトリが存在しない場合のみ作成
       if (!Directory.Exists(path))
       {
          Directory.CreateDirectory(path);
          Console.WriteLine($"ディレクトリの新規作成: {path}");
       }
       else
       {
          Console.WriteLine($"ディレクトリは既に存在する: {path}");
       }
    }
 }


サブディレクトリを含む複数階層のディレクトリを新規作成

複数階層の作成は、複雑なディレクトリ構造を1度に作成することができる。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user/parent/child/grandchild";
 
       try
       {
          // 複数階層のディレクトリを1度に新規作成
          DirectoryInfo di = Directory.CreateDirectory(path);
          Console.WriteLine($"ディレクトリ構造を新規作成: {di.FullName}");
 
          // 作成されたディレクトリの情報を表示
          Console.WriteLine($"作成日時: {di.CreationTime}");
          Console.WriteLine($"親ディレクトリ: {di.Parent.FullName}");
       }
       catch (Exception e)
       {
          Console.WriteLine($"エラーが発生: {e.Message}");
       }
    }
 }



ディレクトリの削除

ディレクトリの削除には、3つのパターンが存在する。

  • 空のディレクトリの削除
  • ディレクトリとその中身の再帰的な削除
  • 安全な削除 (存在確認付き)


ディレクトリの削除は、権限の問題やI/Oエラーが発生する可能性が高いため、エラーハンドリングが重要である。

ディレクトリの削除は高速であるため、非同期処理は必要ない。
ただし、ネットワークドライブ上での操作等、遅延が予想される特殊なケースでは、以下に示すような方法で非同期で実行することができる。

 Task.Run(() => Directory.Delete(path, true));


空のディレクトリの削除

空のディレクトリを削除する。
ただし、ディレクトリが空でない場合は、例外が発生する。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user/emptyDirectory";
 
       try
       {
          // 空のディレクトリを削除
          Directory.Delete(path);
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: ディレクトリが空ではない、または、存在しない {e.Message}");
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
    }
 }


ディレクトリの再帰的削除

再帰的削除は、ディレクトリおよびディレクトリ内を全て削除する。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user/parentDirectory";
 
       try
       {
          // ディレクトリおよびディレクトリ内容を再帰的に削除
          Directory.Delete(path, true);
       }
       catch (DirectoryNotFoundException e)
       {
          Console.WriteLine($"エラー: ディレクトリが存在しない {e.Message}");
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: I/O エラーが発生 {e.Message}");
       }
    }
 }


ディレクトリの存在を確認してから再帰的削除

ディレクトリの存在を確認することにより、安全に削除することができる。
これにより、不要な例外の発生を防ぐことができる。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user/directoryToDelete";
 
       if (Directory.Exists(path))
       {
          try
          {
             // ディレクトリが存在する場合のみ再帰的削除
             Directory.Delete(path, true);
          }
          catch (UnauthorizedAccessException e)
          {
             Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
          }
          catch (IOException e)
          {
             Console.WriteLine($"エラー: I/O エラーが発生 {e.Message}");
          }
       }
       else
       {
          Console.WriteLine($"ディレクトリが存在しない: {path}");
       }
    }
 }



ディレクトリの移動 / 名前変更

C#では、ディレクトリの移動 / 名前変更は、同じDirectory.Moveメソッドを使用する。

ディレクトリの移動 / 名前変更は、権限の問題やI/Oエラーが発生する可能性が高いため、エラーハンドリングが重要である。

ディレクトリの移動 / 名前変更は高速であるため、非同期処理は必要ない。
ただし、ネットワークドライブ上での操作等、遅延が予想される特殊なケースでは、以下に示すような方法で非同期で実行することができる。

 Task.Run(() => Directory.Move(sourcePath, destPath));


※注意
LinuxのファイルシステムはWindowsと異なり、大文字小文字を区別することに注意する。

安全なディレクトリの移動 / 名前変更

以下の例では、移動先のディレクトリが既に存在する場合を考慮した安全な移動方法を示している。
これにより、予期せぬエラーを防ぐことができる。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string sourcePath = "/home/user/sourceDirectory";
       string destPath   = "/home/user/destinationDirectory";
 
       if (Directory.Exists(sourcePath))
       {
          if (!Directory.Exists(destPath))
          {
             try
             {
                Directory.Move(sourcePath, destPath);
             }
             catch (IOException e)
             {
                Console.WriteLine($"エラー: 移動中にI/Oエラーが発生 {e.Message}");
             }
             catch (UnauthorizedAccessException e)
             {
                Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
             }
          }
          else
          {
             Console.WriteLine($"エラー: 移動先のディレクトリが既に存在する: {destPath}");
          }
       }
       else
       {
          Console.WriteLine($"エラー: 移動元のディレクトリが存在しない: {sourcePath}");
       }
    }
 }


ディレクトリの名前変更

以下の例では、ディレクトリの名前変更に特化したプログラムを示している。
これは、同じディレクトリ内でのファイル名の変更に適している。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string dirPath = "/home/user/oldName";
       string newName = "newName";
 
       try
       {
          string newPath = Path.Combine(Path.GetDirectoryName(dirPath), newName);
 
          if (Directory.Exists(dirPath))
          {
             Directory.Move(dirPath, newPath);
          }
          else
          {
             Console.WriteLine($"エラー: 指定されたディレクトリが存在しない: {dirPath}");
          }
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: 名前変更中にI/Oエラーが発生 {e.Message}");
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
    }
 }



ディレクトリの検索

ディレクトリの検索は、権限の問題やディレクトリが見つからない場合のエラーが発生する可能性があるため、エラーハンドリングが重要である。

※注意
Linuxのファイルシステムでは大文字と小文字が区別されることに注意する。
そのため、パターンマッチングを使用する場合は、大文字小文字の違いに気を付ける必要がある。

全てのサブディレクトリの再帰的取得

以下の例では、指定したディレクトリ以下の全てのサブディレクトリを取得している。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path = "/home/user";
 
       try
       {
          // 指定したディレクトリ内の全てのサブディレクトリを再帰的に取得
          string[] directories = Directory.GetDirectories(path, "*", SearchOption.AllDirectories);
 
          foreach (string dir in directories)
          {
             Console.WriteLine(dir);
          }
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (DirectoryNotFoundException e)
       {
          Console.WriteLine($"エラー: 指定されたディレクトリが存在しない {e.Message}");
       }
    }
 }


パターンマッチングを使用したディレクトリ検索

パターンマッチングを使用した方法は、特定のパターンに一致するディレクトリのみを検索する。
これは、特定の名前や形式のディレクトリを探す場合に便利である。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path          = "/home/user";
       string searchPattern = "sample*";  // "sample"で始まるディレクトリを検索
 
       try
       {
          // 指定したパターンに一致するディレクトリを検索
          string[] directories = Directory.GetDirectories(path, searchPattern, SearchOption.AllDirectories);
 
          foreach (string dir in directories)
          {
             Console.WriteLine(dir);
          }
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (DirectoryNotFoundException e)
       {
          Console.WriteLine($"エラー: 指定されたディレクトリが存在しない {e.Message}");
       }
    }
 }


正規表現を使用したディレクトリ検索

正規表現を使用したディレクトリ検索は強力であるが、適切に使用しないとパフォーマンスの問題を引き起こす可能性がある。
使用する場合は、検索対象のディレクトリ構造の規模と正規表現の複雑さを考慮する必要がある。

また、正規表現で大文字と小文字を区別しない検索を行う場合は、RegexOptions.IgnoreCaseオプションを使用する。

以下の例では、正規表現を使用してディレクトリを検索している。

  1. Regex.IsMatchメソッドを使用して、各ディレクトリ名が指定された正規表現パターンに一致するかどうかを確認する。
  2. Path.GetFileNameメソッドを使用して、フルパスからディレクトリ名のみを抽出する。
  3. これにより、パス全体ではなくディレクトリ名のみに対して正規表現マッチングを行うことができる。


ただし、大規模なディレクトリ構造を扱う場合は非同期処理を使用することを推奨する。

 using System;
 using System.IO;
 using System.Text.RegularExpressions;
 
 class Program
 {
    static void Main(string[] args)
    {
       string path    = "/home/user";
       string pattern = @"^sample_\d+$";  // "sample_"で始まり、その後に数字が続くディレクトリを検索
 
       try
       {
          // 指定したディレクトリ内のすべてのサブディレクトリを取得
          string[] allDirectories = Directory.GetDirectories(path, "*", SearchOption.AllDirectories);
 
          // 正規表現パターンに一致するディレクトリをフィルタリング
          var matchingDirectories = Array.FindAll(allDirectories, dir => Regex.IsMatch(Path.GetFileName(dir), pattern));
 
          foreach (string dir in matchingDirectories)
          {
             Console.WriteLine(dir);
          }
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (DirectoryNotFoundException e)
       {
          Console.WriteLine($"エラー: 指定されたディレクトリが存在しない {e.Message}");
       }
       catch (RegexMatchTimeoutException e)
       {
          Console.WriteLine($"エラー: 正規表現のマッチングがタイムアウト {e.Message}");
       }
    }
 }


非同期処理で検索

大規模なディレクトリ構造を扱う場合は時間が掛かる可能性がある。
非同期処理を行うことにより、大規模なディレクトリ構造を扱う場合にアプリケーションの応答性を維持するのに役立つ。

 using System;
 using System.IO;
 using System.Linq;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 
 class Program
 {
    static async Task Main(string[] args)
    {
       string path    = "/home/user";
       string pattern = @"^test_\d+$";
 
       try
       {
          var matchingDirectories = await Task.Run(() => 
          {
             return Directory.GetDirectories(path, "*", SearchOption.AllDirectories)
                    .Where(dir => Regex.IsMatch(Path.GetFileName(dir), pattern))
                    .ToArray();
          });
 
          foreach (string dir in matchingDirectories)
          {
             Console.WriteLine(dir);
          }
       }
       catch (Exception e)
       {
          Console.WriteLine($"エラーが発生: {e.Message}");
       }
    }
 }



ディレクトリのパーミッション

Linuxにおいて、ディレクトリのセキュリティ設定は、主に権限 (パーミッション) の設定を通じて行う。
より細かい制御 (ACLの設定等) が必要な場合は、追加のライブラリやシステムコールが必要になる可能性がある。

.NET 5以降では、System.IO.FileSystem名前空間にUnixFileMode列挙型が追加された。
この列挙型を使用して、UNIX系OSのファイルパーミッションを扱うことができる。

権限の設定は、I/Oエラーが発生する可能性が高いため、エラーハンドリングを実装することが重要である。

※注意 1
ただし、UnixFileModeプロパティはLinux環境でのみ動作することに注意する。

※注意 2
root権限または適切な権限を持つユーザとして実行する必要がある。
そうでない場合、例外UnauthorizedAccessExceptionが発生する可能性がある。

パーミッションの取得

 using System;
 using System.IO;
 
 class DirectoryPermissions
 {
    static void Main(string[] args)
    {
       // ディレクトリのパス
       string dirPath = $"/usr/bin";
 
       // ディレクトリが存在するかどうかを確認
       if (!Directory.Exists(dirPath))
       {
          Console.WriteLine("指定されたディレクトリが存在しない");
          return;
       }
 
       try
       {
          // ディレクトリの情報を取得
          DirectoryInfo dirInfo = new DirectoryInfo(dirPath);
 
          // Unixファイルモードを取得
          UnixFileMode mode = dirInfo.UnixFileMode;
 
          // パーミッションを8進数で表示
          Console.WriteLine($"ディレクトリ: {dirPath}");
          Console.WriteLine($"パーミッション: {Convert.ToString((int)mode, 8).PadLeft(4, '0')}");
 
          // 詳細なパーミッション情報を表示
          Console.WriteLine("詳細:");
          Console.WriteLine($"ユーザー: {((mode & UnixFileMode.UserRead) != 0 ? "r" : "-")}" +
                            $"{((mode & UnixFileMode.UserWrite) != 0 ? "w" : "-")}" +
                            $"{((mode & UnixFileMode.UserExecute) != 0 ? "x" : "-")}");
          Console.WriteLine($"グループ: {((mode & UnixFileMode.GroupRead) != 0 ? "r" : "-")}" +
                            $"{((mode & UnixFileMode.GroupWrite) != 0 ? "w" : "-")}" +
                            $"{((mode & UnixFileMode.GroupExecute) != 0 ? "x" : "-")}");
          Console.WriteLine($"その他:   {((mode & UnixFileMode.OtherRead) != 0 ? "r" : "-")}" +
                            $"{((mode & UnixFileMode.OtherWrite) != 0 ? "w" : "-")}" +
                            $"{((mode & UnixFileMode.OtherExecute) != 0 ? "x" : "-")}");
       }
       catch (Exception ex)
       {
          Console.WriteLine($"エラーが発生: {ex.Message}");
       }
    }
 }


パーミッションの設定

以下の例では、指定したディレクトリのパーミッションを設定している。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string directoryPath = "/home/user/testdir";
 
       try
       {
          // ディレクトリが存在することを確認
          if (Directory.Exists(directoryPath))
          {
             // ディレクトリのパーミッションを755に設定 (例: 755 - rwxr-xr-x)
             File.SetUnixFileMode(directoryPath, UnixFileMode.UserRead     | 
                                                 UnixFileMode.UserWrite    | 
                                                 UnixFileMode.UserExecute  | 
                                                 UnixFileMode.GroupRead    | 
                                                 UnixFileMode.GroupExecute | 
                                                 UnixFileMode.OtherRead    | 
                                                 UnixFileMode.OtherExecute);
 
             // 現在のパーミッションを取得して8進数で表示
             UnixFileMode currentMode = File.GetUnixFileMode(directoryPath);
             Console.WriteLine($"現在のパーミッション: {Convert.ToString((int)currentMode, 8)}");
          }
          else
          {
             Console.WriteLine($"ディレクトリ '{directoryPath}' が存在しない");
          }
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: I/O操作中にエラーが発生 {e.Message}");
       }
    }
 }


再帰的なパーミッションの設定

以下の例では、再帰的にディレクトリとそのサブディレクトリのパーミッションを設定している。

※注意
再帰的処理では、大規模なディレクトリ構造を扱う場合にスタックオーバーフローする可能性がある。
そのような場合は、非再帰的なアプローチや非同期処理を検討する必要がある。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string directoryPath = "/home/user/testdir";
 
       try
       {
          SetPermissionsRecursively(directoryPath);
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: I/O操作中にエラーが発生 {e.Message}");
       }
    }
 
    static void SetPermissionsRecursively(string path)
    {
       // ディレクトリのパーミッションを755に設定 (例: 755 - rwxr-xr-x)
       File.SetUnixFileMode(path, UnixFileMode.UserRead     |
                                  UnixFileMode.UserWrite    |
                                  UnixFileMode.UserExecute  |
                                  UnixFileMode.GroupRead    |
                                  UnixFileMode.GroupExecute |
                                  UnixFileMode.OtherRead    |
                                  UnixFileMode.OtherExecute);
 
       // サブディレクトリに対して再帰的に処理
       foreach (string subDir in Directory.GetDirectories(path))
       {
          SetPermissionsRecursively(subDir);
       }
 
       // ファイルのパーミッションも644に設定する場合 (例: 644 - rw-r--r--)
       foreach (string file in Directory.GetFiles(path))
       {
          File.SetUnixFileMode(file, UnixFileMode.UserRead  |
                                     UnixFileMode.UserWrite |
                                     UnixFileMode.GroupRead |
                                     UnixFileMode.OtherRead);
       }
    }
 }


再帰的なパーミッションの設定 (非同期処理)

以下の例では、非同期処理を使用して、再帰的にディレクトリとそのサブディレクトリのパーミッションを設定している。
大規模なディレクトリ構造を扱う場合は、非同期処理を使用することを推奨する。

 using System;
 using System.IO;
 using System.Threading.Tasks;
 
 class Program
 {
    static async Task Main(string[] args)
    {
       string directoryPath = "/home/user/testdir";
 
       try
       {
          await SetPermissionsRecursivelyAsync(directoryPath);
       }
       catch (Exception e)
       {
          Console.WriteLine($"エラーが発生: {e.Message}");
       }
    }
 
    static async Task SetPermissionsRecursivelyAsync(string path)
    {
       await Task.Run(() =>
       {
          // ディレクトリのパーミッションを755に設定 (例: 755 - rwxr-xr-x)
          File.SetUnixFileMode(path, UnixFileMode.UserRead     |
                                     UnixFileMode.UserWrite    |
                                     UnixFileMode.UserExecute  |
                                     UnixFileMode.GroupRead    |
                                     UnixFileMode.GroupExecute |
                                     UnixFileMode.OtherRead    |
                                     UnixFileMode.OtherExecute);
       });
 
       // サブディレクトリに対して再帰的に処理
       foreach (string subDir in Directory.GetDirectories(path))
       {
          await SetPermissionsRecursivelyAsync(subDir);
       }
 
       // ファイルのパーミッションも644に設定する場合 (例: 644 - rw-r--r--)
       foreach (string file in Directory.GetFiles(path))
       {
          await Task.Run(() =>
          {
             File.SetUnixFileMode(file, UnixFileMode.UserRead  |
                                        UnixFileMode.UserWrite |
                                        UnixFileMode.GroupRead |
                                        UnixFileMode.OtherRead);
          });
       }
    }
 }



ディレクトリの属性

Linuxでは、Windowsのような詳細な属性 (アーカイブ、システム、隠しファイル等) は限られているが、基本的な属性や時間情報等を取得および設定することができる。

DirectoryInfoクラスを使用して、ディレクトリの情報や属性にアクセスする。
また、属性の設定には適切な権限が必要であるため、エラーハンドリングが重要となる。

時間情報 (作成日時、最終アクセス日時、最終更新日時) の変更が可能であるが、これらの操作はファイルシステムの動作に影響を与える可能性があるため、慎重に行う必要がある。

FileAttributes列挙型を使用して属性を設定するが、Linuxでは一部の属性 (例: ReadOnly) のみが有効である。

※注意
不適切な属性の変更は、システムの動作に影響を与える可能性があるため、ファイルシステムの整合性とセキュリティに注意すること。

ディレクトリの属性の取得

以下の例では、Linuxにおいて、ディレクトリの基本的な属性を取得している。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string directoryPath = "/home/user/testdir";
 
       try
       {
          DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
 
          if (dirInfo.Exists)
          {
             Console.WriteLine($"ディレクトリ: {dirInfo.FullName}");
             Console.WriteLine($"作成日時: {dirInfo.CreationTime}");
             Console.WriteLine($"最終アクセス日時: {dirInfo.LastAccessTime}");
             Console.WriteLine($"最終更新日時: {dirInfo.LastWriteTime}");
             Console.WriteLine($"属性: {dirInfo.Attributes}");
 
             // Linuxパーミッションの取得
             UnixFileMode mode = File.GetUnixFileMode(directoryPath);
             Console.WriteLine($"Unixパーミッション: {Convert.ToString((int)mode, 8).PadLeft(4, '0')}");
          }
          else
          {
             Console.WriteLine($"ディレクトリ '{directoryPath}' が存在しない");
          }
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: I/O操作中にエラーが発生 {e.Message}");
       }
    }
 }


ディレクトリの属性の設定

以下の例では、ディレクトリの属性を設定している。

 using System;
 using System.IO;
 
 class Program
 {
    static void Main(string[] args)
    {
       string directoryPath = "/home/user/testdir";
 
       try
       {
          DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
 
          if (dirInfo.Exists)
          {
             // 最終アクセス日時と最終更新日時を設定
             DateTime newTime = DateTime.Now;
             dirInfo.LastAccessTime = newTime;
             dirInfo.LastWriteTime = newTime;
 
             // 属性を設定(例:読み取り専用)
             dirInfo.Attributes |= FileAttributes.ReadOnly;
 
             // 更新後の属性を表示
             Console.WriteLine($"最終アクセス日時: {dirInfo.LastAccessTime}");
             Console.WriteLine($"最終更新日時: {dirInfo.LastWriteTime}");
             Console.WriteLine($"属性: {dirInfo.Attributes}");
          }
          else
          {
             Console.WriteLine($"ディレクトリ '{directoryPath}' が存在しない");
          }
       }
       catch (UnauthorizedAccessException e)
       {
          Console.WriteLine($"エラー: アクセス権限がない {e.Message}");
       }
       catch (IOException e)
       {
          Console.WriteLine($"エラー: I/O操作中にエラーが発生 {e.Message}");
       }
    }
 }


ディレクトリの属性の設定 (非同期処理)

以下の例では、非同期処理を使用して、ディレクトリの属性を設定している。

ネットワークドライブ上での操作等、遅延が予想される特殊な場合では、非同期処理を使用することを推奨する。

 using System;
 using System.IO;
 using System.Threading.Tasks;
 
 class Program
 {
    static async Task Main(string[] args)
    {
       string directoryPath = "/home/user/testdir";
 
       try
       {
          DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
 
          if (dirInfo.Exists)
          {
             await Task.Run(() =>
             {
                DateTime newTime = DateTime.Now;
                dirInfo.LastAccessTime = newTime;
                dirInfo.LastWriteTime = newTime;
 
                dirInfo.Attributes |= FileAttributes.ReadOnly;
             });
          }
          else
          {
             Console.WriteLine($"ディレクトリ '{directoryPath}' が存在しない");
          }
       }
       catch (Exception e)
       {
          Console.WriteLine($"エラーが発生: {e.Message}");
       }
    }
 }