DirectoryUtils.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. namespace MeloongCore;
  2. public static class DirectoryUtils {
  3. /// <summary>
  4. /// 创建文件夹,或文件所在的文件夹。
  5. /// 文件夹已存在时不会抛出异常。
  6. /// </summary>
  7. public static void Create(string path, bool isFilePath = false) {
  8. if (isFilePath) path = PathUtils.RemoveFileName(path);
  9. if (DirectoryUtils.Exists(path)) return;
  10. Logger.Trace($"新建文件夹:{path}");
  11. path = PathUtils.WithLongPath(path);
  12. Directory.CreateDirectory(path);
  13. }
  14. /// <summary>
  15. /// 判断文件夹是否存在。
  16. /// </summary>
  17. public static bool Exists(string path)
  18. => Directory.Exists(PathUtils.WithLongPath(path));
  19. /// <summary>
  20. /// 获取 <see cref="DirectoryInfo"/> 对象。
  21. /// </summary>
  22. public static DirectoryInfo GetInfo(string path)
  23. => new(PathUtils.WithLongPath(path));
  24. /// <summary>
  25. /// 返回指定路径下的所有文件,不以 \\?\ 开头。
  26. /// 如果文件夹不存在,返回空列表。
  27. /// </summary>
  28. public static IEnumerable<string> GetFiles(string path, bool topDirectoryOnly = false, string searchPattern = "*") {
  29. if (!DirectoryUtils.Exists(path)) return [];
  30. Logger.Trace($"枚举文件({searchPattern},递归:{!topDirectoryOnly}):{path}");
  31. return Directory.EnumerateFiles(PathUtils.WithLongPath(path), searchPattern, topDirectoryOnly ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories).
  32. Select(PathUtils.WithoutLongPath);
  33. }
  34. /// <summary>
  35. /// 返回指定路径下的所有文件夹,不以分隔符结尾,不以 \\?\ 开头。
  36. /// 如果文件夹不存在,返回空列表。
  37. /// </summary>
  38. public static IEnumerable<string> GetDirectories(string path, bool topDirectoryOnly = false, string searchPattern = "*") {
  39. if (!DirectoryUtils.Exists(path)) return [];
  40. Logger.Trace($"枚举文件夹({searchPattern},递归:{!topDirectoryOnly}):{path}");
  41. return Directory.EnumerateDirectories(PathUtils.WithLongPath(path), searchPattern, topDirectoryOnly ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories).
  42. Select(PathUtils.WithoutLongPath);
  43. }
  44. /// <summary>
  45. /// 该文件夹是否为空。
  46. /// 如果文件夹不存在,返回 true。
  47. /// </summary>
  48. public static bool IsEmpty(string path) {
  49. if (!DirectoryUtils.Exists(path)) return true;
  50. return !Directory.EnumerateFileSystemEntries(PathUtils.WithLongPath(path)).Any();
  51. }
  52. /// <summary>
  53. /// 复制文件夹。
  54. /// 若原文件夹不存在,则不执行。
  55. /// </summary>
  56. public static void Copy(string sourceDirName, string destDirName, Action<double>? progressHandler = null) {
  57. if (!DirectoryUtils.Exists(sourceDirName)) {
  58. Logger.Info($"尝试复制文件夹,但原文件夹不存在,已跳过复制:{sourceDirName} → {destDirName}");
  59. progressHandler?.Invoke(1);
  60. return;
  61. }
  62. sourceDirName = PathUtils.WithoutLongPath(PathUtils.WithSeparator(sourceDirName)).Replace("/", @"\");
  63. destDirName = PathUtils.WithoutLongPath(PathUtils.WithSeparator(destDirName)).Replace("/", @"\");
  64. int doneCount = 0;
  65. Lazy<int> totalCount = new(() => DirectoryUtils.GetFiles(sourceDirName).Count());
  66. Logger.Trace($"复制文件夹:{sourceDirName} → {destDirName}");
  67. foreach (var file in DirectoryUtils.GetFiles(sourceDirName)) {
  68. FileUtils.Copy(file, file.Replace(sourceDirName, destDirName));
  69. doneCount++;
  70. if (progressHandler is not null) progressHandler?.Invoke((double) doneCount / totalCount.Value);
  71. }
  72. }
  73. /// <summary>
  74. /// 剪切文件夹。
  75. /// </summary>
  76. public static void Move(string sourceDirName, string destDirName) {
  77. if (!DirectoryUtils.Exists(sourceDirName)) return;
  78. DirectoryUtils.Delete(destDirName); // Move 要求不存在对应文件夹
  79. Logger.Trace($"剪切文件夹:{sourceDirName} → {destDirName}");
  80. Directory.Move(PathUtils.WithLongPath(sourceDirName), PathUtils.WithLongPath(destDirName));
  81. }
  82. /// <summary>
  83. /// 删除文件夹。
  84. /// </summary>
  85. public static void Delete(string dirPath, bool toRecycleBin = false) {
  86. if (!DirectoryUtils.Exists(dirPath)) return;
  87. Logger.Trace($"{(toRecycleBin ? "将文件夹删除到回收站" : "删除文件夹")}:{dirPath}");
  88. if (toRecycleBin) {
  89. FileUtils.DeleteToRecycleBin(dirPath);
  90. } else {
  91. Directory.Delete(PathUtils.WithLongPath(dirPath), recursive:true);
  92. }
  93. }
  94. }