Как реализовать glob в C #
Я не знаю, правильно ли StackOverflow публиковать собственный ответ на вопрос, но я видел, что никто этого не спрашивал. Я пошел искать C # Glob и не нашел его, поэтому написал один, который другие могут найти полезным.
- Плавная текстовая анимация (Marquee) с использованием WPF
- Как создать новый шаблон проекта Eclipse?
- Почему использование дикой карты с заявлением на импорт Java плохое?
- Как я могу проверить, является ли тип экземпляром данного шаблона classа?
- Фабричный, абстрактный заводский и заводской метод
- Заводской шаблон. Когда использовать заводские методы?
- подстановочный знак * в CSS для classов
- Как заменить $ {} заполнители в текстовом файле?
/// /// return a list of files that matches some wildcard pattern, eg /// C:\p4\software\dotnet\tools\*\*.sln to get all tool solution files /// /// pattern to match /// all matching paths public static IEnumerable Glob(string glob) { foreach (string path in Glob(PathHead(glob) + DirSep, PathTail(glob))) yield return path; } /// /// uses 'head' and 'tail' -- 'head' has already been pattern-expanded /// and 'tail' has not. /// /// wildcard-expanded /// not yet wildcard-expanded /// public static IEnumerable Glob(string head, string tail) { if (PathTail(tail) == tail) foreach (string path in Directory.GetFiles(head, tail).OrderBy(s => s)) yield return path; else foreach (string dir in Directory.GetDirectories(head, PathHead(tail)).OrderBy(s => s)) foreach (string path in Glob(Path.Combine(head, dir), PathTail(tail))) yield return path; } /// /// shortcut /// static char DirSep = Path.DirectorySeparatorChar; /// /// return the first element of a file path /// /// file path /// first logical unit static string PathHead(string path) { // handle case of \\share\vol\foo\bar -- return \\share\vol as 'head' // because the dir stuff won't let you interrogate a server for its share list // FIXME check behavior on Linux to see if this blows up -- I don't think so if (path.StartsWith("" + DirSep + DirSep)) return path.Substring(0, 2) + path.Substring(2).Split(DirSep)[0] + DirSep + path.Substring(2).Split(DirSep)[1]; return path.Split(DirSep)[0]; } /// /// return everything but the first element of a file path /// eg PathTail("C:\TEMP\foo.txt") = "TEMP\foo.txt" /// /// file path /// all but the first logical unit static string PathTail(string path) { if (!path.Contains(DirSep)) return path; return path.Substring(1 + PathHead(path).Length); }
Я наткнулся на источник, чтобы утюжить ruby, который содержит довольно аккуратный class Glob. Это довольно просто извлечь его из соответствующего кода.
https://github.com/IronLanguages/main/blob/master/Languages/Ruby/Ruby/Builtins/Glob.cs
Вы можете использовать командлет командной строки «dir» (aka «Get-ChildItem») из C #.
(Я не говорю, должны ли вы.)
Вы должны добавить эту ссылку в свой файл проекта (« .csproj» или « .vcproj») вручную:
Подробнее о том, как использовать командлеты с C #, см. Здесь: http://www.devx.com/tips/Tip/42716
Здесь рабочая программа:
using System; using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Collections.ObjectModel; namespace CsWildcard { class Program { static IEnumerable CmdletDirGlobbing(string basePath, string glob){ Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); // cd to basePath if(basePath != null){ Pipeline cdPipeline = runspace.CreatePipeline(); Command cdCommand = new Command("cd"); cdCommand.Parameters.Add("Path", basePath); cdPipeline.Commands.Add(cdCommand); cdPipeline.Invoke(); // run the cmdlet } // run the "dir" cmdlet (eg "dir C:\*\*\*.txt" ) Pipeline dirPipeline = runspace.CreatePipeline(); Command dirCommand = new Command("dir"); dirCommand.Parameters.Add("Path", glob); dirPipeline.Commands.Add(dirCommand); Collection dirOutput = dirPipeline.Invoke(); // for each found file foreach (PSObject psObject in dirOutput) { PSMemberInfoCollection a = psObject.Properties; // look for the full path ("FullName") foreach (PSPropertyInfo psPropertyInfo in psObject.Properties) { if (psPropertyInfo.Name == "FullName") { yield return psPropertyInfo.Value.ToString(); // yield it } } } } static void Main(string[] args) { foreach(string path in CmdletDirGlobbing(null,"C:\\*\\*\\*.txt")){ System.Console.WriteLine(path); } foreach (string path in CmdletDirGlobbing("C:\\", "*\\*\\*.exe")) { System.Console.WriteLine(path); } Console.ReadKey(); } } }