Last active
January 3, 2019 05:22
-
-
Save Dkowald/efed4a9cddb86f6cf2de49b9166a4163 to your computer and use it in GitHub Desktop.
Resolve case-aware path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.IO; | |
| using System.Linq; | |
| // ReSharper disable once CheckNamespace | |
| namespace kwd.gist | |
| { | |
| /// <summary> | |
| /// Utility to resolve file system path with case. | |
| /// </summary> | |
| public static class CaseAwarePath | |
| { | |
| /// <summary> | |
| /// Resolve a Root(ed) path to match file-system case. | |
| /// </summary> | |
| /// <remarks> | |
| /// To improve performance, resolve the root once; subsequent | |
| /// resolution then limited to a specified sub-path. | |
| /// </remarks> | |
| public static DirectoryInfo Root(string root) | |
| { | |
| if (!Path.IsPathRooted(root)) | |
| { | |
| throw new ArgumentException("The path must be absolute.", nameof(root)); | |
| } | |
| var pathRoot = Path.GetPathRoot(root); | |
| var foundPath = Resolve(new DirectoryInfo(pathRoot), root.Substring(pathRoot.Length)); | |
| return new DirectoryInfo(foundPath); | |
| } | |
| /// <summary> | |
| /// Resolve case-aware sub-path; does NOT resolve root. | |
| /// </summary> | |
| /// <param name="root">Root directory, not included in the resolve</param> | |
| /// <param name="subPath">A set of sub-path(s) to resolve</param> | |
| public static string Resolve(DirectoryInfo root, params string[] subPath) | |
| { | |
| if (!root.Exists) | |
| { | |
| return Path.Combine(root.FullName, Path.Combine(subPath)); | |
| } | |
| var segments = new Queue<string>(subPath); | |
| var cur = root.FullName; | |
| while (segments.Any()) | |
| { | |
| var next = segments.Dequeue(); | |
| var part = Path.GetFileName(Directory.GetFileSystemEntries(cur, next).FirstOrDefault()); | |
| if (part != null) | |
| { | |
| cur = Path.Combine(cur, part); | |
| } | |
| else | |
| { | |
| cur = Path.Combine(new[] | |
| {cur, next}.Concat(segments).ToArray()); | |
| break; | |
| } | |
| } | |
| return cur; | |
| } | |
| /// <summary> | |
| /// Resolve case-aware sub-path; does NOT resolve root. | |
| /// </summary> | |
| /// <param name="root">Root directory, not included in the resolve</param> | |
| /// <param name="subPath">A sub-path string</param> | |
| /// <returns>The full path with case matching any sub-path found on file-system</returns> | |
| public static string Resolve(DirectoryInfo root, string subPath) => Resolve(root, | |
| subPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) | |
| .Where(x => !string.IsNullOrEmpty(x)) | |
| .ToArray()); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment