Powershell glob 模式匹配

Powershell glob pattern matching

我正在 C:\ProgramFiles 中查找名为 log4j-core-x.y.z.jar 的 jar 文件。我正在尝试匹配最后一位数字 z,它可以是一位或两位数 (0-99)。我似乎无法获得正确的 glob 模式来完成此任务。

Code:

PS C:\Users\Administrator> Get-ChildItem -Path 'C:\Program Files\' -Filter log4j-core-*.*.[1-9][0-9].jar -Recurse -ErrorAction SilentlyContinue -Force | %{$_.FullName}

这不会产生任何结果,但是当我只使用所有通配符时,-Filter log4j-core-*.*.*.jar,我得到:

C:\Program Files\apache-log4j-2.16.0-bin\apache-log4j-2.16.0-bin\log4j-core-2.16.0-javadoc.jar
C:\Program Files\apache-log4j-2.16.0-bin\apache-log4j-2.16.0-bin\log4j-core-2.16.0-sources.jar
C:\Program Files\apache-log4j-2.16.0-bin\apache-log4j-2.16.0-bin\log4j-core-2.16.0-tests.jar
C:\Program Files\apache-log4j-2.16.0-bin\apache-log4j-2.16.0-bin\log4j-core-2.16.0.jar

我唯一关心的是C:\Program Files\apache-log4j-2.16.0-bin\apache-log4j-2.16.0-bin\log4j-core-2.16.0.jarlog4j-core-2.16.0.jar

-Filter 不支持使用 regexCharacter ranges such as [A-Z] or [0-9]. Thanks 进行过滤以指出这一点。

来自Get-ChildItem官方文档的参数说明:

The filter string is passed to the .NET API to enumerate files. The API only supports * and ? wildcards.

试试这个:

Get-ChildItem -Path 'C:\Program Files\' -Filter log4j-core-*.*.??.jar -Recurse -ErrorAction SilentlyContinue -Force |
Where-Object {
    $_.Name -match '\.\d{1,2}\.jar$'
    # => Ends with a . followed by 1 or 2 digits and the .jar extension
}

offers a regex 辅助解决方案 有可能执行比手头情况所需的复杂得多的匹配。

让我用一个基于 wildcard 的解决方案 来补充它,该解决方案建立在您自己的尝试之上:

  • -Filter参数支持PowerShell的通配符语法;它只支持 *? 作为通配符元字符(如圣地亚哥笔记), 也支持 character-range/set 结构,例如 [0-9].

    • 相反,-Filter 参数由平台的文件系统 API 解释,在 Windows 上还有遗留问题 - 参见 .

    • 也就是说,对于 -Filter 确实支持的模式,它的使用优于 -Include(见下文),因为它的性能要好得多,因为过滤 源头.

  • 相比之下,-Include 参数 确实 使用 PowerShell 的通配符并且另外支持 多个 模式。

与正则表达式不同,character-range/set PowerShell 通配符语言中的表达式支持重复(量词)逻辑并匹配[=每个 55=] 正好一个字符 (就像 ? 任何 单个字符所做的一样;* 是 [=55= 的唯一元字符]隐式 支持重复:零个或多个字符)。

因此,[1-9][0-9]正好匹配2个字符(数字),而只匹配一个个数字([0-9]) 需要一个 附加 模式:

Get-ChildItem -Recurse 'C:\Program Files' -Include log4j-core-*.*.[0-9].jar, log4j-core-*.*.[1-9][0-9].jar -ErrorAction SilentlyContinue -Force | 
  ForEach-Object FullName

注意事项:

  • 使用 -Include(或 -Exclude而不使用 -Recurse 不会像预期的那样工作 - 请参阅.

  • 自 PowerShell 7.2 起,将 -Recurse-Include 组合会因实施效率低下而出现性能问题 - 请参阅 GitHub issue #8662.