21

I have a folder on a server called MyFolder. There are additional folders called MyFolder.1, MyFolder.2, MyFolder.3 etc.

If I run:

gci C:\Sample | ? { $_.Name -like "MyFolder.*" }

I get the expected output:

    Directory: C:\Sample


Mode                LastWriteTime     Length Name                                                                      
----                -------------     ------ ----                                                                      
d----        16/10/2012     12:16            MyFolder.1                                                                
d----        16/10/2012     12:16            MyFolder.2                                                                
d----        16/10/2012     12:16            MyFolder.3  

However if I run:

gci C:\Sample -Filter "MyFolder.*"

I get:

    Directory: C:\Sample


Mode                LastWriteTime     Length Name                                                                      
----                -------------     ------ ----                                                                      
d----        16/10/2012     12:16            MyFolder                                                                  
d----        16/10/2012     12:16            MyFolder.1                                                                
d----        16/10/2012     12:16            MyFolder.2                                                                
d----        16/10/2012     12:16            MyFolder.3                                                                

I'm confused on how MyFolder is included in the output. I'd expect the output to be the same.

The online help highlights that the syntax of the filter is based on the provider but I'm unsure what provider is being used in this instance.

Am I missing a fundamental piece of knowledge here? I've attempted to pass a regex string in to the filter e.g "MyFolder\.*" but this simply returns nothing. I'm sure I'm missing something simple.

I'm running Powershell version 2.

Resolution

Thanks to Roman Kuzmin for pointing out the differences in wildcard matching. The following gives the expected output:

gci C:\Sample\MyFolder.*

I'll be using this syntax for ease in the future to reduce noise in code.

Kieranties
  • 697
  • 1
  • 4
  • 14
  • 4
    It'd be nice if Microsoft updated the help to explain what -Filter does for the Filesystem Provider, since that's probably the 99.9 and a half % most common case where people are using Get-ChildItem. "Syntax is based on provider" seems a little disingenuous. – Todd Walton Jan 04 '18 at 15:08

3 Answers3

23

The Filter of FileSystem provider rather uses CMD wildcards than PowerShell wildcards. CMD wildcards are funny and not intuitive in some edge cases, mostly historically. Here is an interesting explanation: https://devblogs.microsoft.com/oldnewthing/20071217-00/?p=24143

Another gotcha to be kept in mind: ls -Filter *.txt in fact gets files like *.txt* in PowerShell sense, i.e. files with extensions starting with txt. This may be unexpected and very unpleasant in some scenarios :)

Orangutech
  • 769
  • 1
  • 10
  • 17
Roman Kuzmin
  • 40,627
  • 11
  • 95
  • 117
  • Thanks for the link and highlighting the wildcard differences. That's help me resolve the issue (but not in the way I would have expected..) – Kieranties Oct 16 '12 at 12:56
  • Excellent point about `-Filter *.txt` acting like `-Filter *.txt*`. A quibble: The linked article talks about MS-DOS, not CMD (`cmd.exe`). The article goes on to say (emphasis added), "But _some_ quirks of the FCB matching algorithm persist into _Win32_ because they have become idiom.". In other words, the _Windows API_ provides the current behavior, as detailed in [this answer](https://stackoverflow.com/a/17739503/45375). – mklement0 Nov 09 '19 at 23:08
  • 3
    I can vouch for the "unexpected and unpleasant" effect of using -Filter and running a set of SQL scripts against a DB, when one script in the folder was named `filename.sql-skip`. – TTT Feb 23 '21 at 19:43
12
gci C:\Sample -Filter "MyFolder.*"  # here is a filesystem provider; use wildcard `*`,`?`

return the same output as (in a cmd.exe shell):

dir Myfolder.* 

If you need a regex this is the way ( -filter doesn't accept regex)

gci C:\Sample | ? { $_.Name -match '^MyFolder\..*' }

like here

gci C:\Sample | ? { $_.Name -like "MyFolder.*" }

the comparison in the scriptblock is between [string] type.

CB.
  • 58,865
  • 9
  • 159
  • 159
0

here is some info on filter behavior https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7.3

MS example.

When using the -Include parameter, if you don't include an asterisk in the path

the command returns no output.

Get-ChildItem -Path C:\Test\ -Include *.txt

Get-ChildItem -Path C:\Test* -Include *.txt

       Directory: C:\Test

       Mode                LastWriteTime         Length Name
      ----                -------------         ------ ----
      -a----        2/13/2019     08:55             26 anotherfile.txt
      -a----        2/12/2019     15:40         118014 Command.txt
      -ar---        2/12/2019     14:31             27 ReadOnlyFile.txt
HandyManny
  • 37
  • 2