Как реализовать глобус на С#

Я не знаю, разрешено ли в StackOverflow публиковать собственный ответ на вопрос, но я видел, что никто еще не спрашивал об этом. Я пошел искать C# Glob и не нашел его, поэтому я написал тот, который может оказаться полезным для других.


person Community    schedule 29.12.2008    source источник
comment
После некоторого поиска в Google я нашел, что должен делать glob. en.wikipedia.org/wiki/Glob_(программирование)   -  person tuinstoel    schedule 29.12.2008
comment
Вы бы получили больше баллов, если бы не сделали это вики сообщества. :-)   -  person George Stocker    schedule 30.12.2008
comment
Почему я получил больше баллов? Я здесь новенький ...   -  person Mark Maxham    schedule 02.01.2009
comment
Просто для справки: глобусы выглядят как path***.txt   -  person Daniel Little    schedule 19.12.2014
comment
@Mark, потому что ответы Community Wiki не присуждают баллы, каждый голос обычно дает вам 10 баллов.   -  person Daniel Little    schedule 19.12.2014


Ответы (4)


Я наткнулся на источник железа ruby, который содержит довольно аккуратный класс Glob. Его довольно легко извлечь из связанного кода.

https://github.com/IronLanguages/main/blob/master/Languages/Ruby/Ruby/Builtins/Glob.cs

person Community    schedule 13.05.2010

Вы можете использовать командлет powershell "dir" (также известный как "Get-ChildItem") из C#.
(я не говорю, следует ли вам это делать).

Вы должны добавить эту ссылку в файл проекта (".csproj" или ".vcproj") вручную:

<Reference Include="System.Management.Automation" />

Дополнительные сведения об использовании командлетов 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<string> 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 (e.g. "dir C:\*\*\*.txt" )
            Pipeline dirPipeline = runspace.CreatePipeline();
            Command dirCommand = new Command("dir");
            dirCommand.Parameters.Add("Path", glob);
            dirPipeline.Commands.Add(dirCommand);

            Collection<PSObject> dirOutput = dirPipeline.Invoke();

            // for each found file
            foreach (PSObject psObject in dirOutput) {

                PSMemberInfoCollection<PSPropertyInfo> 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();
        }

    }
}
person Community    schedule 27.08.2013

это легко с https://github.com/dazinator/DotNet.Glob:

пример:

public static class Glob
{
  public static IEnumerable<FileInfo> Exec(DirectoryInfo dir, string glob)
  {
    var matcher = DotNet.Globbing.Glob.Parse(glob);
    return dir.EnumerateAllFiles().Where(f => matcher.IsMatch(f.FullName));
  }

  public static IEnumerable<FileInfo> EnumerateAllFiles(this DirectoryInfo dir)
  {
    foreach (var f in dir.EnumerateFiles())
    {
      yield return f;
    }

    foreach (var sub in dir.EnumerateDirectories())
    {
      foreach (var f in EnumerateAllFiles(sub))
      {
        yield return f;
      }
    }
  }
}
person Community    schedule 22.01.2019
comment
Откуда вы получаете DirectoryInfo? Если у меня есть просто строковый глобус, я не хочу писать логику для извлечения базового каталога... - person jjxtra; 14.04.2020
comment
У вас может быть собственная версия, в которой базовый каталог — это просто текущий каталог запущенного процесса. Также пример может быть легко расширен для поддержки нескольких базовых каталогов. - person sergeyt; 15.04.2020
comment
"DirectoryInfo" не содержит определения ошибки "EnumerateAllFiles". - person vee; 11.01.2021
comment
Метод расширения @vee EnumerateAllFiles определен в классе Glob в моем фрагменте кода. Вы можете изменить его на версию без расширения. Я не уверен, почему вы получаете эту ошибку. - person sergeyt; 17.01.2021

person    schedule
comment
Ошибка? Мне пришлось заменить Path.Combine(head, dir) на dir, поскольку Directory.GetDirectories уже возвращает полный путь. Это вызвало ошибку с такими путями, как ..\SomeDir*.dll, поскольку ..\ дублировались Combine. - person jturcotte; 05.03.2009
comment
Похоже, это не работает, если вы передаете строку типа * функции Glob. Делаются ли какие-то предположения относительно строки с подстановочными знаками, которую он может обрабатывать? Может быть, абсолютный путь? - person Ben; 30.09.2011
comment
Метод Glob разбивает аргумент на две части по адресу DirSep. Код не работает, если нет Dirsep. Добавление следующего оператора в начало метода PathHead работает: if (! path.Contains(DirSep)) {return ".";}. - person AdrianHHH; 30.07.2015
comment
@Ben Предполагается, что строка содержит DirSep. С изменением моего предыдущего комментария код работает для меня. - person AdrianHHH; 17.08.2015