Поиск файлов с использованием wild card в С#

Я пытаюсь найти файлы из каталога:

String[] search1 = Directory.GetFiles(voiceSource, "85267-*.wav")
                                 .Select(path => Path.GetFileName(path))
                                 .ToArray();

String[] search2 = Directory.GetFiles(voiceSource, "85267 *.wav")
                                 .Select(path => Path.GetFileName(path))
                                 .ToArray();

Но в search1 он выбирает как 85267-s.wav, так и 85267 -s.wav. Но я хочу выбрать только 85267-s.wav.

search2 преуспевает.

Как я могу это сделать?

Ответы

Ответ 1

Поведение, которое вы испытываете, связано с коротким именем файла. Поскольку вы получите 85267-~1.WAV для 85267 -s.wav, и поскольку это соответствует вашей дикой карте "85267-*.wav", вы получите оба файла обратно.

Объясняется в Directory.GetFiles Method (String, String)

Поскольку этот метод проверяет наличие имен файлов как с файлом 8.3 формат имени и формат длинного имени файла, аналогичный шаблон поиска to "1.txt" может возвращать неожиданные имена файлов. Например, используя шаблон поиска "1.txt" вернет "longfilename.txt", потому что эквивалентный формат имени файла 8.3 будет "longf ~ 1.txt".

Для обхода вы можете использовать Directory.EnumerateFiles, чтобы сначала выбрать оба файла, соответствующие вашим критериям, а затем сравнить фактическую (длинную) часть имени файла с помощью StartsWith. Помните EnumerateFiles ленивая оценка.

String[] search1 = Directory.EnumerateFiles(@"C:\test", "85267-*.wav")
                         .Where(file => Path.GetFileName(file).StartsWith("85267-"))
                         .Select(path => Path.GetFileName(path))
                         .ToArray();

Ответ 2

Да, это побочный эффект поддержки коротких имен MS-Dos 8.3, который по-прежнему включен сегодня в большинстве файловых систем. Что-то, что вы видите с помощью команды DIR/X, отображает эти короткие имена. На моей машине:

C:\temp>dir /x *.wav

01/21/2015  09:11 AM                 6 85267-~1.WAV 85267 -s.wav
01/21/2015  09:11 AM                 6              85267-s.wav
               2 File(s)             12 bytes
               0 Dir(s)  235,121,160,192 bytes free

Обратите внимание на то, что краткое имя для "85267-s" не содержит пробела. Это короткое имя не является допустимым. То, что осталось теперь, также соответствует вашему шаблону.

Это не то место, где проблема заканчивается этими короткими именами. Подстановочный знак, такой как *.wav, также будет соответствовать файлу типа foobar.wavx, совершенно другого типа файла.

Краткосрочное поколение - это, откровенно говоря, реликт прошлого века, который сегодня нужно отключить. Но это обычно не то, что вы можете контролировать сами. Вам приходится иметь дело с этими случайными матчами и проверять, что вы вернете. Например, с помощью Regex.