0

I have no trouble with Get-ChildItem using * as a wildcard, but I wonder if it can be made to work with more refined wild cards. Given a file like C:\Folder\journal.0001.txt I would want to use the wildcard C:\Folder\journal.####.txt to get all "regular" journal files, but skip the ones named with this format journal.0000.worker1.log. Using the wildcard in the path throws an error that the path doesn't exist, and replacing the file bit with a simple * and the using journal.####.txt as a filter or include doesn't work. I do see that journal.????.txt works, but that would potentially grab journal.ABCD.txt should it exist. And I haven't even started playing with character sets.

Gordon
  • 6,257
  • 6
  • 36
  • 89
  • Due to the sometimes huge differences between versions, especially core vs previous, use the tag indicating the version of PS instead of the general `powershell` tag. – Dávid Laczkó Jun 13 '21 at 06:44

2 Answers2

4

Compared to RegEx wildcard patterns have a limited metacharacter set, and no quantifiers I know of, It does support character ranges like:

Get-ChildItem C:\temp\06-11-21\journal.[0-9][0-9][0-9][0-9].txt

Oddly, this only works as part of the path. It doesn't seem to work when specified as an argument to -Filter or -Include.

about_Wildcards

You can post filter the files using Where-Object or a For-EachObject loop with RegEx if you need more flexibility.

Steven
  • 6,817
  • 1
  • 14
  • 14
  • As for `-Filter`: it uses the file-system's wildcard expressions, which don't support character sets/ranges (`[...]`); as for `-Include`: unfortunately, it only acts on the leaf components of the _input path_, not its children - see [this answer](https://stackoverflow.com/a/38308796/45375). – mklement0 Jun 12 '21 at 23:30
0

I have a saved link that discusses problems with -Include and -Exclude. I got there as I had problems with filtering, and ever since I use Where-Object for that purpose. I dont't know if there is a more compact way to do this, but I used it like this with a multi-parameter file search:

Get-ChildItem ... |
Where-Object {$_.Extension -in $FileExtensionIN -or $FileExtensionIN.Count -eq 0} |
Where-Object {$_.Extension -notin $FileExtensionNOTIN -or $FileExtensionNOTIN.Count -eq 0} |
Where-Object {$_.Name -match $FileNameMATCH -or $FileNameMATCH -eq ""} |
Where-Object {$_.Name -notmatch $FileNameNOTMATCH -or $FileNameNOTMATCH -eq ""} |
...

It is not compact, but at least also not cryptic.

Steven
  • 6,817
  • 1
  • 14
  • 14
Dávid Laczkó
  • 1,091
  • 2
  • 6
  • 25
  • 1
    The linked problem is a bug specific to `-LiteralPath` vs. `-Path` that plagues _Windows PowerShell_, but has fortunately been fixed in PowerShell (Core) as of (at least) v7.0. However there is still questionable by-design behavior in the absence of `-Recurse`: `-Include` and `-Exclude` only apply to the _input_ paths, not to their _children_; the workaround is to use `Get-ChildItem * -Include ... / -Exclude ...` - see [this answer](https://stackoverflow.com/a/38308796/45375). – mklement0 Jun 13 '21 at 03:31
  • @mklement0 Thanks for your input. This also strengthens me to use post-filtering, as there are still caveats & workarounds with a lot of explanations which is so tiring that I don't want to test... nevertheless your pedantic coverage of use-cases is impressive - keep up the good work! :). The second thing is of course, that the whole thing needed to be checked twice, in v5.1 & core... – Dávid Laczkó Jun 13 '21 at 06:27
  • All sorts of great info here. In my case I can't use it in this particular situation, but noted for other situations. And as to WHY I can't use it, the specific issue I have is that I am working with path data that is provided by the user in an XML file, and I need to limit my data to a single data item for now. So any wild card MUST be part of the path. In future I may be able to support additional elements in the XML to support a filter value, but for now I can't. So for now the solution @Steven provided is my best option. It covers 95% of situations, just not as tersely as I had hoped for. – Gordon Jun 13 '21 at 08:02
  • 1
    @DávidLaczkó, yes, the situation is still a mess, unfortunately. The potential problem with post-filtering - while sometimes unavoidable to implemented more sophisticated matching - is diminished performance, which can matter in large directory trees. At least that's the theory - in practice, as of PowerShell 7.2 `-Include` / `-Exclude` are _slower_ than post-filtering(!), but that can and should be fixed - see [GitHub issue #8662](https://github.com/PowerShell/PowerShell/issues/8662) (sigh). `-Filter` - _if_ its abilities are sufficient in a given scenario - is always fastest. – mklement0 Jun 13 '21 at 18:54
  • 1
    I've updated the guidance in the [linked answer](https://stackoverflow.com/a/38308796/45375), but I can definitely see why one wouldn't bother and just use post-filtering instead. I'll attempt a tl;dr here: If you're using `-Recurse`, everything works as expected, in both editions. Otherwise, if you're using _PowerShell v7+_ and the input paths are literals, use `-LiteralPath` instead of `-Path` (does _not_ work in _Windows PowerShell_). Otherwise, switch to `Get-Item` and append `\*` to the input paths (passed to `-Path`). – mklement0 Jun 13 '21 at 19:12