Powershell,文件系统提供程序,Get-ChildItem过滤......官方文档在哪里?

时间:2011-07-08 18:37:04

标签: powershell

正如another question中所述,如果您尝试执行Get-ChildItem -filter ...命令,则比使用-include代替-filter更有限。我想阅读文件系统提供程序的过滤语法的官方文档,但经过半小时的搜索后,我仍然没有找到它们。谁知道在哪里看?

4 个答案:

答案 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_DOTANSI_DOS_DOT
  • <相当于MS-DOS ?(ntifs.h中的DOS_QMANSI_DOS_QM
  • >相当于MS-DOS *(ntifs.h中的DOS_STARANSI_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是我发现的最佳来源。这是基本的想法:

  • 每个文件名正好是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")。如果您从命令提示符自行测试这些内容,则可能需要将它们转义(例如,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会自动消除参数名称的歧义,但是从来没有伤害过它:)