tl; dr -Filter
использует реализацию .NET FsRtllsNameInExpression
, которая документирована в MSDN вместе с базовой информацией о сопоставлении с образцом. Алгоритм не является интуитивно понятным по причинам совместимости, и вам, вероятно, следует избегать использования этой функции. Кроме того, .NET имеет множество ошибок в своей реализации.
-Filter
не использует систему фильтрации, предоставляемую PowerShell, то есть не использует систему фильтрации, описанную Get-Help about_Wildcard
. Скорее, он передает фильтр в Windows API. Поэтому фильтрация работает так же, как и в любой другой программе, использующей Windows API, например cmd.exe
.
Вместо этого PowerShell использует FsRtlIsNameInExpression
-подобный алгоритм для сопоставления с образцом фильтра. Алгоритм основан на старом поведении 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
ошибочно рассматривает "<>
как недопустимые, не подстановочные символы . (Это позволяет .*?
.) Это способствует пониманию того, что -Filter является неполным, нестабильным и глючным. Вы можете увидеть реализацию (. Глючного) .NET (10) * на 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 дает значительно отличающиеся результаты при тестировании этих "ошибок". Протестировано с WINE 1.9.6.
Как видите, обратно совместимые подстановочные знаки MS-DOS неясны и содержат ошибки. Даже Microsoft реализовала их неправильно хотя бы один раз , и неясно, является ли их текущее поведение в Windows преднамеренным. Поведение "
кажется совершенно случайным, и я ожидал, что результаты двух последних тестов поменяются местами.