I am looking through C:\ProgramFiles for a jar file named log4j-core-x.y.z.jar. I am trying to match on the last digit z, which can be both a one or two digit number (0-99). I can't seem to get the right glob pattern to accomplish this.
Code:
PS C:\Users\Administrator> Get-ChildItem -Path 'C:\Program Files\' -Filter log4j-core-*.*.[1-9][0-9].jar -Recurse -ErrorAction SilentlyContinue -Force | %{$_.FullName}
This yields no results, but when I just do all wildcards like, -Filter log4j-core-*.*.*.jar, I get:
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
The only thing I care about getting is C:\Program Files\apache-log4j-2.16.0-bin\apache-log4j-2.16.0-bin\log4j-core-2.16.0.jar, log4j-core-2.16.0.jar
-Filter doesn't support filtering with regex or Character ranges such as [A-Z] or [0-9]. Thanks mklement0 for pointing it out.
From the parameter description of Get-ChildItem official documentation:
The filter string is passed to the .NET API to enumerate files. The API only supports
*and?wildcards.
Try with this:
$getChildItemSplat = @{
Path = 'C:\Program Files\'
Filter = 'log4j-core-*.*.??.jar'
Recurse = $true
ErrorAction = 'SilentlyContinue'
Force = $true
}
Get-ChildItem @getChildItemSplat |
# Ends with a . followed by 1 or 2 digits and the .jar extension
Where-Object Name -Match '\.\d{1,2}\.jar$'
Santiago Squarzon's helpful answer offers a regex-assisted solution that has the potential to perform much more sophisticated matching than required in the case at hand.
Let me complement it with a wildcard-based solution that builds on your own attempt:
The -Filter parameter does not support PowerShell's wildcard syntax; it only supports * and ? as wildcard metacharacters (as Santiago notes), not also character-range/set constructs such as [0-9].
Instead, -Filter arguments are interpreted by the platform's file-system APIs, which on Windows additionally have legacy quirks - see this answer.
That said, with patterns that -Filter does support, its use is preferable to -Include (see below), because it performs much better, due to filtering at the source.
By contrast, the -Include parameter does use PowerShell's wildcards and additionally supports multiple patterns.
Unlike regexes, character-range/set expressions in PowerShell's wildcard language do not support duplication (quantifier) logic and match exactly one character each (just like ? does for any single character; * is the only metacharacter that implicitly supports duplication: zero or more characters).
Therefore, [1-9][0-9] matches exactly 2 characters (digits), and also matching just one digit ([0-9]) requires an additional pattern:
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
Caveats:
Using -Include (or -Exclude) without -Recurse doesn't work as one would expect - see this answer.
As of PowerShell 7.2, combining -Recurse with -Include suffers from performance problems due to inefficient implementation - see GitHub issue #8662.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With