问题
In one of the questions I answered recently I found interesting answer which shouldn't be working but still was. The question was about how to find specific folder recursively by its name and cd
to it.
The answer proposed by A guest who's called Redd was:
Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
As per the documentation of Get-ChildItem, -Name
parameter is supposed to be SwitchParameter
type and is responsible for returning only name (System.String
), instead of System.Object
.
How it's possible that the solution still works?
MCVE:
# cd C:\SO\56628221
mkdir test, test1, test2, test3
mkdir .\test2\folder
Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
Current output:
test2\folder
Expected output:
Get-ChildItem : A positional parameter cannot be found that accepts argument 'Folder'.
What have I tried?
- First I checked that
-Path
is the only positional parameter. Apparently it is:
All the other params have Position: Named
.
- Then I tried to switch the arguments to something like this:
Get-ChildItem -Path .\ Folder -Name -Recurse -Depth 10
It was still working, so that was clear indication that what I'm passing to the cmdlet is not the value for -Name
.
- Last thing I supposed was that I just send array of strings to
-Path
. I tried to do this explicitely:
[string[]]$a = '.\','Folder'
$a.GetType()
Get-ChildItem -Path $a -Name -Recurse -Depth 10
# Output:
PS C:\SO\56628221> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String[] System.Array
PS C:\SO\56628221> Get-ChildItem -Path $a -Name -Recurse -Depth 10
test
test1
test2
test3
test2\folder
Get-ChildItem : Cannot find path 'C:\SO\56628221\Folder' because it does not exist.
At line:1 char:1
+ Get-ChildItem -Path $a -Name -Recurse -Depth 10
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\SO\56628221\Folder:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
回答1:
tl;dr:
Apparently there's an incorrect information in current version of Get-ChildItem
documentation, stating that -Filter
is no longer positional.
The above is no longer true, it's been fixed in this PR.
Long answer:
In fact, the value 'Folder' is being passed to -Filter
parameter. Even though PowerShell 6 documentation says opposite, -Filter
is a positional parameter. By mistake, that change was introduced in PowerShell v6+ while PowerShell 5.1 help article for Get-ChildItem is still correct.
The cmdlet you run:
Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
is effectively:
Get-ChildItem -Path ".\" -Name -Filter "Folder" -Recurse -Depth 10
Even though -Filter
parameter in Get-ChildItem
might be tricky in usage, in that case it works perfectly and the filter is applied to only show items named 'Folder'. As that invocation doesn't specify -File
or -Directory
, if you run:
# Create new file named 'Folder'
New-Item Folder
and then run the cmdlet once again, it'd return both file and folder which was created:
PS C:\SO\56628221> Get-ChildItem -Path .\ -Name Folder -Recurse -Depth 10
Folder
test2\folder
The output is exactly the same if you explicitely use -Filter
:
PS C:\SO\56628221> Get-ChildItem -Path .\ -Name -Filter Folder -Recurse -Depth 10
Folder
test2\folder
来源:https://stackoverflow.com/questions/56632954/is-it-possible-to-filter-using-get-childitem-name