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

1

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

weird that technet's own examples don't use recurse parameter. Thanks!
@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.
-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).
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.