1

When using "-filter":

Get-ChildItem -file -filter "*.txt" | foreach-object { write-host $_.FullName }

I get a listing of the 4 .txt files that's in the current folder.

I tried using "-include"

Get-ChildItem -file -include *.txt | foreach-object { write-host $_.FullName }
Get-ChildItem -file -include *txt | foreach-object { write-host $_.FullName }

and I get nothing. I tried with and without the "-file" parameter and it makes no difference.

I've looked at various guides/examples (ss64.com/TechNet and etc) and supposedly I am doing it right.

Any ideas what I could be doing wrong? Thanks!

enter image description here

mrjayviper
  • 2,258
  • 11
  • 46
  • 82
  • related: https://stackoverflow.com/questions/33684178/powershell-5-get-childitem-literalpath-doesnt-work-with-include-anymore – Ohad Schneider Nov 14 '17 at 15:02

2 Answers2

5

From the Get-Help page for Get-ChildItem:

The -Include parameter is effective only when the command includes the -Recurse parameter or the path leads to the contents of a directory, such as C:\Windows*, where the "*" wildcard character specifies the contents of the C:\Windows directory.

You'll note that you don't get a syntax error if you specify -include and don't specify -recurse in spite of the fact that whatever it does is literally undefined. You'll also note that C:\Windows* is not a normal wildcard expression for "all files in the C:\Windows directory". It's a wildcard expression for "all items that start with 'Windows' in the C:\ directory and may or may not have an extension". I have no idea what the authors of Get-ChildItem think this parameter is supposed to do. They've done a fantastically poor job of documenting it and implementing it.

Consequently, I avoid the -Include parameter as broken/badly documented. I don't know what it's supposed to do that -Filter doesn't. I've read articles about what it does exactly. It "passes the value to the underlying provider to filter at that level" in some manner. I don't know why they assume that a sysadmin will know what that really means. My understanding is that it's the difference between calling DirectoryInfo.GetFiles() on each directory item and calling DirectoryInfo.GetFiles('*.txt') on each directory item, but most sysadmins aren't going to know what that means. However, it's so oddly behaved that I don't trust it, so even though I am about 95% sure of what it does... I still never use it.

Instead, I just pipe to Where-Object:

Get-ChildItem -file | Where-Object Extension -eq '.txt' | [...]

Also note that Get-ChildItem is broken with -LiteralPath, -Recurse and -Include in some versions of PowerShell, and will instead return all items.

Compare:

Get-ChildItem -LiteralPath $PSHOME *.exe -Recurse # works
Get-ChildItem -Path $PSHOME -Include *.exe -Recurse # works
Get-ChildItem -LiteralPath $PSHOME -Include *.exe -Recurse # does NOT work

Issue reported here for v6.

Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
  • weird that technet's own examples don't use recurse parameter. Thanks! – mrjayviper Nov 01 '17 at 04:43
  • 1
    @mrjayviper `-Include` and `-Exclude` also get ignored when you use `-LiteralPath`. I forgot about that one, but it's been a bug for ages in some versions. – Bacon Bits Nov 01 '17 at 12:40
  • `-Filter` is limited to one pattern string (`-Include` supports multiple). And as you implied, `-Filter` is both typically more efficient and works properly with `-LiterlPath` and `-Recurse`. So to sum up, if you only need one pattern, use `-Filter`. If you need multiple patterns use `where` as you suggested (which is basically equivalent to `-Include` anyway as the filtering is done by PowerShell rather than the underlying provider). – Ohad Schneider Nov 14 '17 at 15:11
1

These work for me without recursion:

Get-ChildItem -Path "C:\Users\Athom\Desktop\*.txt"


Get-ChildItem -Path ".\*.txt"

Or Just add the recursion parameter:

 Get-ChildItem -Include *.txt -Recurse
Austin T French
  • 5,022
  • 1
  • 22
  • 40