OK, so I feel like this must be a bug in PowerShell, but I wanted to see if you guys think this sounds broken. It's quite an easy thing to reproduce, but I can see why it might not be a particularly common use case. The steps I've put below aren't actually what my script was doing, I was actually calculating sizes of subfolders - I've just condensed it down to the simplest possible scenario that shows my problem.
I have only tried this on PowerShell 5.0.10240.16384, but might soon have the chance to test it on an earlier version [Edit: I have now tested this on PowerShell 2.0, and the bug does not appear in that version - it works as expected]. Just a quick note - I've used gci
throughout as an abbreviation for Get-ChildItem. If you didn't already know, this works to actually type into PowerShell too. But the problem exists whatever alias you use.
First, create a folder called Test [123]
somewhere handy. In that folder, create a couple of files. Mine are caled Test1.txt
and Test2.txt
. They don't need to have anything in them.
Next, open a PowerShell session and Set-Location
to the parent folder of your new Test [123]
folder.
Now, run gci -Filter Test*
and you should see something like:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/15/2015 3:22 PM Test [123]
All good, right? Next, try gci -Filter Test* | gci
. This makes the output of the first gci the input for the next one, ie shows us the children of each item the first gci returns. This gives us the following:
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/14/2015 10:21 PM 0 Test1.txt
-a---- 11/15/2015 3:55 PM 0 Test2.txt
Again, all good - exactly as expected. This is all the files from our Test [123]
folder.
Now try this: gci -Filter Test* | gci -Recurse
. All we've changed is that the second call to gci
is now recursive, so it should show us all files including subfolders. We don't have any subfolders, so we're expecting the same results, right?
Wrong. We don't get any output at all. Seems very odd that all we've done is added -Recurse
and now we get different output. I think that adding -Recurse
should never render less output, only ever more.
Here's the next weird thing. Now try gci -Filter Test* | gci -Recurse -Name
. This is the same as before except with the -Name
parameter added. This is simply saying that we want the same output, except we only want the filenames and not the full information about each item. So we're probably expecting nothing back. But that's not what we get, we get this:
Test1.txt
Test2.txt
This has got to be broken, right? Firstly -Recurse
should never reduce the amount of output, and secondly asking for the output in a different format should not change the amount of output we get.
This only happens when there are square brackets in the name of the folder. If you create another folder, just called Test
, and run all the commands above again, you will always see the files from the Test
folder.
My research lead me to the -LiteralPath
parameter; however, rephrasing the above command as gci -Filter Test* | foreach { gci -Recurse -LiteralPath $_ }
, so as to use that parameter, still returns no output, and again, adding the -Name
parameter starts the files being returned again.
I've managed to do a workaround for this, using the -Name
parameter and then combining it with the path of the folder I'm searching, then passing that into Get-Item
, but that's made the code longer and uglier than it needs to be.
So my question is, have I made a mistake or misunderstood something? Or is this a bug I should report?
-Include *
as workaround. – user4003407-Recurse
implementation handles the wildcard characters ([
and]
) in the Name. If you escape them manually, it works as well – Mathias R. Jessen[Regex]::Replace
instead of[System.Management.Automation.WildcardPattern]::Escape
? – user4003407Get-ChildItem
cmdlet is a complete mess. It's one thing in PS, that never produces consistent output. – beatcracker