Рейтинг:
44
Abhishek Sur
Каталог.GetFiles фактически внутренне вызывает Win32 native FindNextFile, чтобы получить все файлы, соответствующие шаблону поиска.
Поскольку ваша windows состоит как из длинных, так и из коротких имен файлов (8,3), она будет соответствовать всему после 3 букв в расширении.
Если вы попробуете Dir *.exe в командной строке DOS, то увидите аналогичный вывод.
Я думаю, что вам нужно использовать
var files = Directory.GetFiles(dir, "*.exe").Where(item => item.EndsWith(".exe"));
Nish Nishant
Проголосовали 5. предложили в качестве ответа.
AspDotNetDev
Это все равно будет соответствовать файлу под названием "file.exexe", что было бы неверно. Но хорошее понимание имен файлов DOS.
Nish Nishant
- Вот именно. EndsWith должен проверить наличие ".exe".
Sergey Alexandrovich Kryukov
Так вот, это правильный обходной путь для Windows lame.
Мой 5.
--СА
Henry Minute
Очень хорошо, Абишек! +5
Sergey Alexandrovich Kryukov
Я также добавил улучшение случая в свой последний ответ.
--СА
Sergey Alexandrovich Kryukov
Абхишек,
Большое вам спасибо за то, что вы тогда объяснили мне эту проблему.
Кроме того, ToLower следует добавить туда, где он должен быть полностью правильным-см. Мой новый ответ.
--СА
Рейтинг:
2
DaveyM69
На этот[^] страница, в разделе заметок говорится::
When using the question mark wildcard character, this method returns only files that match the specified file extension. For example, given two files, "file1.txt" and "file1.txtother", in a directory, a search pattern of "file?.txt" returns just the first file, while a search pattern of "file*.txt" returns both files.
Я еще не пробовал, но хотел бы что-то вроде
*?.exe
сделать это?
Sergey Alexandrovich Kryukov
Нет, *?.exe ничем не отличается от *.exe. "?" означает ровно один (любой) символ, который будет поглощен"*".
DaveyM69
@SAKryukov: Вы правы - я неправильно прочитал документацию.
Этот блог объясняет это лучше, чем MSDN: http://www.simple-talk.com/community/blogs/andras/archive/2008/08/01/65554.aspx
Похоже, что нет другого решения, кроме как проверять каждый возвращенный результат...
Рейтинг:
13
Sergey Alexandrovich Kryukov
[РЕДАКТИРОВАТЬ]
Смотрите мой первоначальный ответ ниже.
Этот вид подстановочных знаков слишком прост.
Неверно, что "file.exeandsomethingelse" не соответствует "*.exe". Этот шаблон верен, если вы просто хотите получить "все имена файлов, заканчивающиеся на '.exe'". А вы пробовали?
Если шаблон был "*.exe*", то да, "file.exeandsomethingelse" будет соответствовать ему. Не путайте с небрежным либеральным отношением к подстановочным знакам в поиске Windows.
Одно замечание, на всякий случай: в файловой системе больше нет такого понятия, как "расширение". Нет, это точно линия в Unix. Точка внутри имени обрабатывается как любой другой символ (она не ставится рядом с разделителем каталогов). (Не путайте его с оболочкой "extension", которая все еще используется в зарегистрированных "типах файлов".)
К сожалению, Галабелла и Нишант были правы, а я ошибался — мои извинения.
Голос "1" за мой ответ был совершенно правильным.
Я только что протестировал его и обнаружил, что он работает так, как документировано Microsoft:
When using the asterisk wildcard character in a searchPattern, such as "*.txt", the matching behavior when the extension is exactly three characters long is different than when the extension is more or less than three characters long. A searchPattern with a file extension of exactly three characters returns files having an extension of three or more characters, where the first three characters match the file extension specified in the searchPattern. A searchPattern with a file extension of one, two, or more than three characters returns only files having extensions of exactly that length that match the file extension specified in the searchPattern. When using the question mark wildcard character, this method returns only files that match the specified file extension. For example, given two files, "file1.txt" and "file1.txtother", in a directory, a search pattern of "file?.txt" returns just the first file, while a search pattern of "file*.txt" returns both files.
В следующем списке показано поведение различных длин для параметра searchPattern:
"*.abc" возвращает файлы с расширением .abc, .abcd, .abcde, .abcdef и так далее.
"*.abcd" возвращает только файлы с расширением .abcd.
"*.abcde" возвращает только файлы с расширением .abcde.
"*.abcdef" возвращает только файлы с расширением .abcdef.
Ниже это странное поведение получает некоторое объяснение:
Примечание:
Поскольку этот метод проверяет имена файлов как с форматом имени файла 8.3, так и с форматом длинного имени файла, шаблон поиска, подобный "*1*.txt", может возвращать неожиданные имена файлов. Например, использование шаблона поиска "*1*.txt" возвращает "longfilename.txt" потому что эквивалентный формат имени файла 8.3-это "LONGFI~1.txt".
То, что мы имеем здесь, я бы назвал эпическим провалом Microsoft, это делает этот API не очень пригодным для использования, если нам нужно разумное маскирующее поведение. Его нужно обойти.
Это похоже на один из случаев "это не ошибка, это функция".
Надо сказать, во всех снарядах я использовал маскировочные работы, как и ожидал.
Еще раз прошу прощения за неприятности, вызванные неправильным ответом.
Смотрите также: добавлено
ToLower
в моем другом ответе.
—СА
Espen Harlinn
5+, Хороший ответ :)
Nish Nishant
Эй Крюков,
Это неверно. Каталог.GetFiles не работает таким образом. *.exe будет соответствовать a.exe а также a.exe2. Это сделано специально и также задокументировано.
Sergey Alexandrovich Kryukov
Неужели? Если вы правы, API-это бесполезное дерьмо. Я хочу проверить это сейчас...
--СА
Nish Nishant
Это не проблема .NET, это поведение Win32 API.
Видишь ли http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/49cbae5b-9c54-432e-9f0e-0fd1f94db287
Sergey Alexandrovich Kryukov
Кто бы сомневался, что это вопрос "должен умереть"?
Уровень новой функциональности .NET всегда лучше; это всего лишь некоторое взаимодействие.
Что забавно, даже старое мерцание в компонентах, созданных в Windows 3*, все еще существует.
Спасибо.
--СА
Sergey Alexandrovich Kryukov
К сожалению, вы с ОПОМ правы. (Я проверил на V. 3.5). И да, это согласно документации.
Это должно умереть!
Извините, я исправлю свой ответ.
--СА
Sergey Alexandrovich Kryukov
Я исправил свой ответ и признал свою ошибку.
--СА
Sergey Alexandrovich Kryukov
К сожалению, кто-то проголосовал "1" абсолютно правильно, Пожалуйста, смотрите мой комментарий.
Я исправлю свой ответ.
Microsoft, к сожалению, работает сейчас как "это должно быть", но "как документально подтверждено".
--СА
fjdiewornncalwe
Не знаю, почему вы получили 1. Отличный и обстоятельный ответ. +5 от меня.
Nish Nishant
Я не голосовал за 1, но ответ неверен.
Sergey Alexandrovich Kryukov
Но голосование "1" было цитатой правильной, см. мое обновление.
--СА
Sergey Alexandrovich Kryukov
Голос "1" является действительным. То, что я сказал, неправда. Я должен это признать (см. Мой комментарий)
--СА
fjdiewornncalwe
Теперь я тоже исправляюсь. Это то, что я узнал сегодня... Но ваша честность в признании ошибки означает, что я, тем не менее, сохраню свой голос на 5.
Sergey Alexandrovich Kryukov
Ну что ж, спасибо. В конце концов, я сам придумал ответ.
--СА
Рейтинг:
1
Sergey Alexandrovich Kryukov
Немного исправим правильный ответ Абхишека Сура:
const string ExtExe = ".exe";
const string MaskExe = "*" + ExtExe;
//..
var files =
Directory.GetFiles(dir, MaskExe).Where(item => item.ToLower().EndsWith(ExtExe));
Я думаю что это хорошо сделать предикат
Where
без учета регистра.
—СА
Jonathan Gilbert
Строка.Метод EndsWith имеет перегрузку, которая принимает значение перечисления StringComparison. Таким образом, вместо того, чтобы создавать новую строку для каждого элемента в нижнем регистре, я считаю, что вы можете сэкономить время и отток памяти, как это:
.Где(номенклатура =&ГТ; пункт.EndsWith(ExtExe, StringComparison.InvariantCultureIgnoreCase))
(Это также выводит вычисления культуры из уравнения-поскольку мы знаем, что сравниваем со строкой ".exe", не имеет значения, какова текущая локаль, потому что правила верхнего/нижнего регистра для расширения файла ".exe" в значительной степени гарантируют, что они не будут включать особые случаи, зависящие от культуры. Основная строка.Метод ToLower() основан на чертах характера для текущей локали.)
Sergey Alexandrovich Kryukov
Согласитесь, что это улучшение полезно и наиболее практично, но я считаю, что за кулисами оно занимает почти столько же циклов памяти и процессора. Но его можно измерить...
Спасибо Вам за этот комментарий.
--СА
Jonathan Gilbert
Я только что сравнил его и обнаружил, что в моей системе вариант, который не создает новый строковый объект, почти в два раза быстрее. Для 10 000 000 циклов, каждый из которых содержит 8 различных капитализаций с различными статусами pass/fail:
.EndsWith(StringComparison): 00:00:08.5870000 9,316,408.52 / сек
.ToLower().EndsWith(): 00:00:15.9700000 5,009,392.61 / сек
Sergey Alexandrovich Kryukov
Ну что ж, интересный результат, Спасибо, что поделились. В критических по времени ситуациях это может быть неплохим поводом для улучшения некоторого кода :-)
--СА