none
Directory.EnumerateFiles() аргумент searchPattern RRS feed

  • Вопрос

  • Не совсем ожидаемое поведение Directory.EnumerateFiles().

    При указании в качестве searchPattern например "*.log" в результаты выборки попадают например файлы "*.logs".

    Т.е. получается логика работы не соответствует описанию:

    For example, the searchPattern string "*t" searches for all names in path that end with the letter "t". The searchPattern string "s*" searches for all names in path that begin with the letter "s". линк

    Это баг или всё таки фича?

    2 ноября 2012 г. 13:29

Ответы

  • Да, действительно. Скорее всего это немного неточное описание функции, а может и баг, так как за кулисами вызывается функция Win API "HANDLE WINAPI FindFirstFile",

    Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); 
    
                // Open a Find handle 
                _hnd = Win32Native.FindFirstFile(searchPath, data);
    
                if (_hnd.IsInvalid)
                { 
                    int hr = Marshal.GetLastWin32Error();
                    if (hr != Win32Native.ERROR_FILE_NOT_FOUND && hr != Win32Native.ERROR_NO_MORE_FILES) 
                    { 
                        HandleError(hr, searchData.fullPath);
                    } 
                    else
                    {
                        // flag this as empty only if we're searching just top directory
                        // Used in fast path for top directory only 
                        empty = searchData.searchOption == SearchOption.TopDirectoryOnly;
                    } 
                } 

    а она глотает много чего, в ней символ '*' означает местозаполнитель и строки вида:

    e:\\temp\\*.log

    e:\\temp\\*.logs попадают под шаблон. Как выход можете использовать такой вариант:

    namespace Test
    {
      class Program
      {
        static void Main(string[] args)
        {
          var files = DirectoryExtender.GetFiles("e:\\temp\\", SearchOption.TopDirectoryOnly);
        }
      }
      public static class DirectoryExtender
      {
        public static IEnumerable<string> GetFiles(string path,SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
          Regex reSearchPattern = new Regex(@".log$");
          return Directory.EnumerateFiles(path, "*", searchOption).Where(file => reSearchPattern.IsMatch(Path.GetExtension(file)));
        }
      }
    }

    • Предложено в качестве ответа Алексей ЛосевEditor 6 ноября 2012 г. 6:47
    • Помечено в качестве ответа tulosba 6 ноября 2012 г. 8:21
    2 ноября 2012 г. 20:34
    Модератор

Все ответы

  • Да, действительно. Скорее всего это немного неточное описание функции, а может и баг, так как за кулисами вызывается функция Win API "HANDLE WINAPI FindFirstFile",

    Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); 
    
                // Open a Find handle 
                _hnd = Win32Native.FindFirstFile(searchPath, data);
    
                if (_hnd.IsInvalid)
                { 
                    int hr = Marshal.GetLastWin32Error();
                    if (hr != Win32Native.ERROR_FILE_NOT_FOUND && hr != Win32Native.ERROR_NO_MORE_FILES) 
                    { 
                        HandleError(hr, searchData.fullPath);
                    } 
                    else
                    {
                        // flag this as empty only if we're searching just top directory
                        // Used in fast path for top directory only 
                        empty = searchData.searchOption == SearchOption.TopDirectoryOnly;
                    } 
                } 

    а она глотает много чего, в ней символ '*' означает местозаполнитель и строки вида:

    e:\\temp\\*.log

    e:\\temp\\*.logs попадают под шаблон. Как выход можете использовать такой вариант:

    namespace Test
    {
      class Program
      {
        static void Main(string[] args)
        {
          var files = DirectoryExtender.GetFiles("e:\\temp\\", SearchOption.TopDirectoryOnly);
        }
      }
      public static class DirectoryExtender
      {
        public static IEnumerable<string> GetFiles(string path,SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
          Regex reSearchPattern = new Regex(@".log$");
          return Directory.EnumerateFiles(path, "*", searchOption).Where(file => reSearchPattern.IsMatch(Path.GetExtension(file)));
        }
      }
    }

    • Предложено в качестве ответа Алексей ЛосевEditor 6 ноября 2012 г. 6:47
    • Помечено в качестве ответа tulosba 6 ноября 2012 г. 8:21
    2 ноября 2012 г. 20:34
    Модератор
  • О, как. Оказалось, что ещё в мае 2010 об этом было известно. линк (см.комментарий Zyprexia)

    P.S. Не проверял в .Net 4.5. Там так же?
    • Изменено tulosba 6 ноября 2012 г. 8:23
    6 ноября 2012 г. 8:21
  • Скорее всего да, вызов Win API тот же. Вечером, проверю, точно скажу.
    6 ноября 2012 г. 8:28
    Модератор