正如another question中所述,如果您尝试执行Get-ChildItem -filter ...
命令,则比使用-include
代替-filter
更有限。我想阅读文件系统提供程序的过滤语法的官方文档,但经过半小时的搜索后,我仍然没有找到它们。谁知道在哪里看?
答案 0 :(得分:16)
tl; dr -Filter
使用.NET的FsRtllsNameInExpression
实现,documented on MSDN以及基本模式匹配信息。出于兼容性原因,该算法不直观,您应该避免使用此功能。此外,.NET在其实现中存在许多错误。
-Filter
不使用PowerShell提供的过滤系统 - 也就是说,不使用Get-Help about_Wildcard
描述的过滤系统。相反,它将过滤器传递给Windows API。因此,过滤的工作方式与使用Windows API的任何其他程序(例如cmd.exe
)相同。
相反,PowerShell使用类似FsRtlIsNameInExpression
的算法进行-Filter模式匹配。该算法基于旧的MS-DOS行为,因此它充满了为传统目的而保留的警告。通常说它有三个常见的特殊字符。确切的行为很复杂,但它或多或少如下:
*
:匹配任意数量的字符(包含零)?
:匹配一个字符,不包括名称中的最后一个字段.
:如果模式中的最后一个句点,则锚定到文件名中的最后一个句点,如果没有句点,则锚定到文件名的结尾;也可以匹配文字句号为了使事情变得更复杂,Windows添加了三个额外的特殊字符,其行为与旧的MS-DOS特殊字符完全相同。现在,原始特殊字符的行为略有不同,以便考虑更灵活的文件系统。
"
相当于MS-DOS .
(ntifs.h中的DOS_DOT
和ANSI_DOS_DOT
<
相当于MS-DOS ?
(ntifs.h中的DOS_QM
和ANSI_DOS_QM
>
相当于MS-DOS *
(ntifs.h中的DOS_STAR
和ANSI_DOS_STAR
相当多的消息来源似乎都会反转<
和>
。可怕的是,Microsoft confuses them in their .NET implementation,这意味着它们在PowerShell中也是相反的。此外,-Filter
中的所有三个兼容通配符都不可用,System.IO.Path
mistakenly treats "<>
as invalid, non-wildcard characters。 (它允许.*?
。)这有助于 -Filter不完整,不稳定和错误的概念。您可以看到算法on GitHub的.NET(错误)实现
此算法对8.3 compatibility filenames的支持更加复杂,也称为“短”文件名。 (您之前可能已经看过它们了;它们看起来像:SOMETH~1.TXT
)如果文件的完整文件名或与其短文件名匹配,则该文件与该模式匹配。 FrankFranchise has more information about this caveat in his answer.
以前链接的FsRtlIsNameInExpression
上的MSDN文章提供了有关Windows文件名模式匹配的最新文档,但它并不特别详细。有关如何在MS-DOS上使用匹配以及它如何影响现代匹配的更全面的解释,this MSDN blog article是我发现的最佳来源。这是基本的想法:
?
匹配任何单个字符,但扩展名.
将用空格填充前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
("
)。如果您从命令提示符自行测试这些内容,则可能需要将它们转义(例如,cmd.exe中的dir ^>^"^>
以模拟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通配符是模糊和错误的。 Even Microsoft has implemented them incorrectly at least once,目前还不清楚他们目前在Windows中的行为是否是故意的。 "
的行为似乎是完全随机的,我期望交换最后两个测试的结果。
答案 1 :(得分:8)
-filter
几乎没有。
当你Get-Help Get-ChildItem -full
时,有一点点,但我确定你seen it。 Powershell博客上还有一个post。不举例。
我能找到的最好的例子是this one,它只是证明了过滤器是一个字符串,提供者用它来返回它本来会返回的子集,甚至不能直接演示-filter
但只是使用它。但是,它比其他链接更好一瞥。
但是,因为提供程序在结果返回cmdlet之前进行过滤,所以有一些警告。例如,如果我想递归查找以“test”开头的所有文件和目录,我会不想要从这开始:
Get-ChildItem -filter 'test*' -recurse
这将在返回递归的任何内容之前过滤当前目录中的所有结果。如果我有一个以“test”开头的目录,它将递归该目录(因为提供程序会将其返回到cmdlet),但没有其他目录。
如示例所示,它可以解决某些提供程序中的属性。在FileSystem提供程序中,您可能只能在目录或文件的名称上使用通配符匹配字符串(leaf,而不是完全限定)。
答案 2 :(得分:3)
关于follow up提及的Zenexer,您应该看到 about 与使用cmd.exe相同的过滤器所看到的相同结果。这包括您可能没有想到的内容,例如 8.3短文件名。你可以自己测试一下。
使用PowerShell创建一些示例文件
md filtertest | cd
(1..1000) | % { New-item -Name ("aaaaa{0:D6}.txt" -f $_) -ItemType File }
现在打开cmd提示符并运行
dir /x
dir aaab*
第一个命令显示8.3短名称。第二个匹配一些文件,即使在任何普通名称中没有'b'字符,因为这些文件在短名称中包含'b'。
现在您可以回到PowerShell并运行ls -Filter aaab*
以再次查看相同的文件。 -Filter
字符串传递给WinAPI,它与8.3短名称中带有'b'的文件匹配,就像cmd.exe中的dir
一样。因此,在使用-Filter
时要注意未公开的结果,您可能会匹配8.3短名称。
这是假设您的计算机上启用了8.3短名称。
答案 3 :(得分:-3)
它们与所有cmdlet的文档位于同一位置。在提示符下键入:
Get-Help Get-ChildItem
如果这不足以告诉你,那么:
Get-Help Get-ChildItem -Detailed
或者,如果你真的想深入研究:
Get-Help Get-ChildItem -Full
编辑:虽然-Detail可以正常工作,因为PS会自动消除参数名称的歧义,但是从来没有伤害过它:)