13

Right now I updated to Windows 10 TH2 Build 10586 with PowerShell 5.0.10586.0

Now I got a problem with Get-ChildItem

$files = Get-ChildItem -LiteralPath $path -Force -Recurse -Include *.txt 

This returns ALL files in $path even they are not .txt. This was working before the update. When I change it to

$files = Get-ChildItem -Path $path -Force -Recurse -Include *.txt 

it works again. But that's not what I want. Is this a bug or am I doing something wrong?

3
  • 1
    what's $path in there, does it have a \ at the end? Commented Nov 13, 2015 at 1:30
  • I have tested both. With and without \ at the end. Doesn't make any difference. Commented Nov 14, 2015 at 0:11
  • The bug still affects 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. Commented Jun 13, 2021 at 3:33

3 Answers 3

11

Personally, I never use -Include or -Exclude anymore. I always pipe through Where-Object. I don't know if the author of -Include and -Exclude was insane or if there's a problem with the underlying .Net provider, but they're flaky as hell.

I'm on 5.0.10240.16384.

gci -Path $path -Include *.txt -Force 

Returns nothing.

gci -LiteralPath $path -Include *.txt -Force 

Returns everything in $path.

gci -LiteralPath $path -Include *.txt -Force -Recurse gci -Path $path -Include *.txt -Force -Recurse 

Both return *.txt in $path and all subfolders.

So what's the proper behavior supposed to be? Does the -Recurse flag modify how -Include works? I don't know. I no longer care. I'm not going to deal with that kind of behavior. I just use this:

gci -Path $path -Recurse -Force | Where-Object { $_.Extension -eq '.txt' } 

I rely on Get-ChildItem to enumerate files and folders and that's it. Just give me the objects and I'll filter them. Like all the old Remove-Item -Recurse bugs, there's something there that just doesn't work the way people expect it to.

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

6 Comments

@MarcFauser Hm, you're right. The doc also says that -Include modifies the -Path argument and says nothing at all about the -LiteralPath argument. Christ, why doesn't this cmdlet emit errors for unsupported syntax? And I have no idea what to make of Example 3, which explicitly talks about using -Path and -Include without -Recurse! Again I'm left asking, "What's the proper behavior supposed to be?" I'd probably post on Microsoft Connect, for all the good it will do.
@BaconBits probably knows this 2 years on, but for people visiting the answer is that the cmdlet doesn't know about unsupported syntax - it just passes them down to the PS Provider subsystem - wildcard behaviour for the filesystem PS Provider is different from the registry provider and from the ActiveDirectory provider, etc. And I suspect that's also why it's "flaky as hell" - because the filesystem wildcards are backwards compatible to Windows 3 or MS-DOS era. It's also why the docs can't say much but "qualifies the path" because it depends on the PSProvider implementation.
@TessellatingHeckler flaky as hell and probably much more efficient - especially if you have a folder with many files and you want to filter most of them out.
@user206904 Yes, even in PS v7.3 I still see unexpected behavior.
@TessellatingHeckler Commenting from further in the future, this explanation for the flaky behavior isn't accurate. -Filter is the parameter that passes along the pattern to the underlying provider, -Include and -Exclude explicitly do not, hence why -Filter has slightly different behavior than -Include, even when using the FileSystem provider. It looks like it's just "flaky as hell" because the way PowerShell handles these parameters is nonsensical.
|
3

Note that -Filter does not seem to have this issue. This works:

$files = Get-ChildItem -LiteralPath $path -Force -Recurse -Filter *.txt 

Filter is also more efficient, because it is used by the underlying provider (as opposed to Include which is applied by PowerShell itself, much like a where clause added by your code).

However Filter only accepts one pattern parameter, whereas Include supports multiple patterns.

1 Comment

Unfortunately -Filter can only handle one filter, not multiple includes
2

I think this is a regression. I submitted it as v5 regression: Get-ChildItem -LiteralPath -Recurse ignores -Include and gets all items

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.