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

Vim*_*mes 14 powershell

正如提到另外一个问题,如果你尝试做一个Get-ChildItem -filter ...命令你比,如果你使用的更有限-include替代-filter.我想阅读文件系统提供程序的过滤语法的官方文档,但经过半小时的搜索后,我仍然没有找到它们.谁知道在哪里看?

Zen*_*xer 17

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_DOTANSI_DOS_DOTntifs.h)
  • <相当于MS-DOS ? (DOS_QMANSI_DOS_QMntifs.h)
  • >相当于MS-DOS * (DOS_STARANSI_DOS_STARntifs.h)

不少人士似乎扭转<>.可怕的是,微软将它们混淆在.NET实现中,这意味着它们在PowerShell中也是相反的.此外,所有三个兼容性通配符都不可用-Filter,因为System.IO.Path错误地将其"<>视为无效的非通配符.(它允许.*?.)这有助于 - 过滤器不完整,不稳定和有缺陷的概念. 您可以在GitHub上看到.NET的(错误)算法实现.

算法对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        
Run Code Online (Sandbox Code Playgroud)

推断这与现代文件系统一起使用是一个不直观的过程.例如,获取如下目录:

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
Run Code Online (Sandbox Code Playgroud)

我已经在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
Run Code Online (Sandbox Code Playgroud)

注意:在编写时,WINE的匹配算法在测试这些"陷阱"时会产生明显不同的结果.用WINE 1.9.6测试.

正如您所看到的,向后兼容的MS-DOS通配符是模糊和错误的. 甚至微软也至少错误地实现过一次,目前还不清楚他们目前在Windows中的行为是否是故意的.行为"似乎是完全随机的,我期望最后两个测试的结果被交换.


Joe*_*ant 8

几乎什么都没有-filter.

当你做的时候有一点点Get-Help Get-ChildItem -full,但我相信你已经看过了.Powershell博客上还有一篇文章.都不举例.

我能找到的最好的例子就是这个,它只是演示了过滤器是一个字符串,提供者用它来返回它本来会返回的子集,而且它甚至不是直接演示-filter而是简单地使用它.但是,它比其他链接更好一瞥.

但是,因为提供程序在结果返回到cmdlet之前进行过滤,所以有一些警告.例如,如果我想递归发现,以"test"开头的所有文件和目录,我就不会想开始这样的:

Get-ChildItem -filter 'test*' -recurse
Run Code Online (Sandbox Code Playgroud)

这将在返回递归的任何内容之前过滤当前目录中的所有结果.如果我有一个以"test"开头的目录,它将递归该目录(因为提供程序会将其返回到cmdlet),但没有其他目录.

如示例所示,它可以解决某些提供程序中的属性.在FileSystem提供程序中,您可能只能在目录或文件名上使用通配符匹配字符串(leaf,而不是完全限定).