Странная функциональность в .NET Directory.GetFiles(), когда шаблон поиска содержит 3 символа для расширения

Недавно я столкнулся со странной функциональностью от Microsoft:

Предположим, наша папка c:\tmp123 содержит 3 файла -
1.txt
2.txtx
3.txtxt

a) Вызов Directory.GetFiles(@"C:\tmp123", "*.txt") дает 3 возвращенных элемента.
b) Вызов Directory.GetFiles(@"C:\tmp123", "*.txtx") дает 1 возвращенный элемент.

Согласно Microsoft, это ожидаемое поведение (см. примечание в MSDN) .

Мои вопросы:

  1. Почему Microsoft решилась на такой странный функционал?

  2. Как решить эту проблему?
    т. е. как создать шаблон поиска, который будет возвращать только расширение *.txt и не будет возвращать *.txtx, *.txtstarngefunctionality и т. д.?


person user1140419    schedule 10.01.2012    source источник


Ответы (4)


Причиной этого является обратная совместимость.

Windows изначально была построена как графический интерфейс поверх MSDOS, в которой были файлы только с 8 символами для имени и максимум 3 для расширения. Расширения файловых систем MSDOS позволили Windows иметь более длинные имена файлов и расширения, но они по-прежнему будут отображаться как имена файлов 8.3 в MSDOS.

Поскольку командная строка в Windows представляет собой эволюцию старого интерпретатора команд в MSDOS, это означает, что некоторые «анахроничные» модели поведения (например, трехбуквенный шаблон поиска) были сохранены, поэтому приложения и сценарии, созданные в «старые времена» или «старые таймеры» не сломается.

(другим примером является тот факт, что большинство файловых систем Windows нечувствительны к регистру, да, как вы уже догадались, потому что у MSDOS не было регистра)

person linkerro    schedule 10.01.2012

Если вам нужен обходной путь, вы можете просто получить все пути к файлам

var files = Directory.GetFiles(@"C:\tmp123");

а затем фильтровать их по расширению по мере необходимости

var txtFiles = files.Where(f => f.EndsWith(".txt"));
var txtxFiles = files.Where(f => f.EndsWith(".txtx"));
person Jeff LaFay    schedule 10.01.2012

Я готов поспорить, что это как-то связано с обратной совместимостью. Я не вижу упоминания именно об этой проблеме, но этот Рэймонд Сообщение в блоге Чена упоминает ряд странностей в этой области:

[...] некоторые причуды алгоритма сопоставления FCB сохраняются в Win32, потому что они стали идиомами.

Например, если ваш шаблон заканчивается на .*, .* игнорируется. Без этого правила шаблон *.* соответствовал бы только файлам, содержащим точку, что, вероятно, нарушило бы 90% всех пакетных файлов на планете, а также мышечную память каждого, поскольку все, кто работает с Windows NT 3.1, выросли в мире, где *.* означает все файлы.

Другой пример: шаблон, оканчивающийся точкой, на самом деле не соответствует файлам, оканчивающимся на точку; он соответствует файлам без расширения. И знак вопроса может соответствовать нулю символов, если он стоит непосредственно перед точкой.

person Community    schedule 10.01.2012

Вот еще один обходной путь, который поможет отфильтровать файлы с такими расширениями, как «.txtxt»:

var Files = System.IO.Directory.GetFiles("*.txt").Where(item => item.Extension.ToString().ToLower() == ".txt");
person sudeep    schedule 24.09.2014