Ответ 1
tl; dr -Filter
использует .NET-реализацию FsRtllsNameInExpression
, которая задокументирована в MSDN вместе с базой данных соответствия шаблону. Алгоритм неинтуитивный по соображениям совместимости, и вам, вероятно, следует избегать использования этой функции. Кроме того,.NET имеет множество ошибок в своей реализации.
-Filter
не использует фильтрующую систему, предоставленную PowerShell, то есть не использует систему фильтрации, описанную Get-Help about_Wildcard
. Скорее, он передает фильтр в Windows API. Поэтому фильтрация работает так же, как и в любой другой программе, использующей Windows API, например cmd.exe
.
Вместо этого PowerShell использует FsRtlIsNameInExpression
-подобный алгоритм для сопоставления шаблонов Filter. Алгоритм основан на старом поведении MS-DOS, поэтому он пронизан предостережениями, которые сохраняются в устаревших целях. Обычно говорят, что у него три общих специальных символа. Точное поведение является сложным, но оно более или менее похоже на следующее:
-
*
: Соответствует любому числу символов (ноль включительно) -
?
: соответствует точно одному символу, исключая последний период в имени -
.
: если последний период в шаблоне привязывается к последнему периоду в имени файла или к концу имени файла, если у него нет периода; может также соответствовать буквальному периоду
Чтобы усложнить ситуацию, Windows добавила три дополнительных специальных символа, которые ведут себя точно так же, как и старые специальные символы MS-DOS. Оригинальные специальные символы теперь имеют немного другое поведение для учета более гибких файловых систем.
-
"
эквивалентен MS-DOS.
(DOS_DOT
иANSI_DOS_DOT
в ntifs.h) -
<
эквивалентен MS-DOS?
(DOS_QM
иANSI_DOS_QM
в ntifs.h) -
>
эквивалентен MS-DOS*
(DOS_STAR
иANSI_DOS_STAR
в ntifs.h)
Довольно много источников, похоже, обращаются к <
и >
. Пугающе, Microsoft путает их в своей реализации .NET, что означает, что они также отменены в PowerShell. Кроме того, все три символа совместимости недопустимы с -Filter
, поскольку System.IO.Path
ошибочно обрабатывает "<>
как недопустимые, несимвольные символы. (Это позволяет .*?
.) Это способствует пониманию того, что -фильтр является неполным, неустойчивым и ошибочным. Вы можете увидеть реализацию .NET(глючной) алгоритма на GitHub.
Это дополнительно усложняется поддержкой алгоритма для 8.3 файлов совместимых файлов, иначе называемых "короткими" именами файлов. (Вероятно, вы видели их раньше: они выглядят примерно так: SOMETH~1.TXT
) Файл соответствует шаблону, если его полное имя файла или совпадает с его коротким именем файла. FrankFranchise имеет больше информации об этом предостережении в своем ответе.
Ранее связанная статья MSDN на FsRtlIsNameInExpression
содержит самую последнюю документацию по совпадению шаблонов имен файлов Windows, но она не является особенно подробной. Для более подробного объяснения того, как соответствие используется для работы с MS-DOS и как это влияет на современное соответствие, эта статья блога MSDN является лучшим источником Я нашел. Вот основная идея:
- Каждое имя файла было равно 11 байтам.
- Первые 8 байтов хранят тело имени файла, с правом пробела с пробелами
- Последние 3 байта сохраняют расширение, с правом пробела с пробелами
- Буквы были преобразованы в верхний регистр.
- Буквы, числа, пробелы и некоторые символы соответствуют только самим себе.
-
?
соответствует любому одиночному символу, кроме пробелов в расширении -
.
заполнит оставшуюся часть первых 8 байтов пробелами, затем переместится на 9-й байт (начало расширения) -
*
заполнит оставшуюся часть текущего раздела (тело или расширение) вопросительными знаками, затем перейдите к следующему разделу (или концу шаблона)
Преобразования будут выглядеть так:
11
User 12345678901
------------ -----------
ABC.TXT > ABC TXT
WILDCARD.TXT > WILDCARDTXT
ABC.??? > ABC ???
*.* > ???????????
*. > ????????
ABC. > ABC
Экстраполирование этого для работы с современными файловыми системами - это, в лучшем случае, неинтуитивный процесс. Например, возьмите директорию, такую как:
Name Compat Name
-----------------------------------------------
Apple1.txt APPLE1 .TXT
Banana BANANA .
Something.txt SOMETH~1.TXT
SomethingElse.txt SOMETH~2.TXT
TXT.exe TXT .EXE
TXT.eexe TXT~1 .EEX
Wildcard.txt WILDCARD.TXT
Я довольно много тестировал эти подстановочные знаки в Windows 10 и получил очень непоследовательные результаты, особенно DOS_DOT
("
). Если вы проверите их самостоятельно из командной строки, вам, вероятно, потребуется их избежать (например, dir ^>^"^>
в cmd.exe для эмуляции MS-DOS *.*
).
*.* (everything)
<"< (everything)
* (everything)
< Banana
. (everything)
" (everything)
*. Banana
<" Banana
*g.txt Something.txt
<g.txt Something.txt
<g"txt (nothing)
*1.txt Apple1.txt, Something.txt
<1.txt Apple1.txt, Something.txt
<1"txt (nothing)
*xe TXT.eexe, TXT.exe
<xe (nothing)
*exe TXT.eexe, TXT.exe
<exe TXT.exe
??????.??? Apple1.txt, Asdf.tx, Banana, TXT.eexe, TXT.exe
>>>>>>.>>> Apple1.txt, Asdf.tx, TXT.eexe, TXT.exe
>>>>>>">>> Banana
????????.??? (everything)
>>>>>>>>.>>> (everything except Banana)
>>>>>>>>">>> Banana
???????????.??? (everything)
>>>>>>>>>>>.>>> (everything except Banana)
>>>>>>>>>>>">>> Banana
?????? Banana
>>>>>> Banana
??????????? Banana
>>>>>>>>>>> Banana
???????????? Banana
???? (nothing)
>>>> (nothing)
Banana??. Banana
Banana>>. Banana
Banana>>" Banana
Banana????. Banana
Banana>>>>. Banana
Banana>>>>" Banana
Banana. Banana
Banana" Banana
*txt Apple1.txt, Something.txt, SomethingElse.txt, Wildcard.txt
<txt Apple1.txt, Something.txt, SomethingElse.txt, Wildcard.txt
*t Apple1.txt, Something.txt, SomethingElse.txt, Wildcard.txt
<t (nothing)
*txt* Apple1.txt, Something.txt, SomethingElse.txt, TXT.eexe, TXT.exe, Wildcard.txt
<txt< Apple1.txt, Something.txt, SomethingElse.txt, Wildcard.txt
*txt< Apple1.txt, Something.txt, SomethingElse.txt, Wildcard.txt
<txt* Apple1.txt, Something.txt, SomethingElse.txt, TXT.eexe, TXT.exe, Wildcard.txt
Примечание. С точки зрения написания алгоритм соответствия WINE дает значительно разные результаты при тестировании этих "gotchas". Протестировано с помощью WINE 1.9.6.
Как вы можете видеть, обратные совместимые шаблоны MS-DOS неясны и ошибочны. Даже Microsoft внедрила их неправильно хотя бы один раз, и неясно, является ли их текущее поведение в Windows преднамеренным. Поведение "
кажется совершенно случайным, и я ожидал, что результаты двух последних тестов будут заменены.