Powershell: Get-ChildItem -Recurse with -Name does not recurse

Created on 28 Feb 2019  ยท  9Comments  ยท  Source: PowerShell/PowerShell

Steps to reproduce

Get-ChildItem -Path *.txt -Recurse -Force -Name

In a folder with for example

S:\play\dir-demo> tree /f
Folder PATH listing for volume Source
Volume serial number is E68B-B87E
S:.
โ”‚   File.txt
โ”‚
โ”œโ”€โ”€โ”€sub1
โ”‚   โ”‚   File.txt
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€โ”€subsub1
โ”‚   โ”‚       File.txt
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€โ”€subsub2
โ”‚           File.txt
โ”‚
โ”œโ”€โ”€โ”€sub2
โ”‚       File.txt
โ”‚
โ””โ”€โ”€โ”€sub3
        File.txt

Expected behavior

Relative paths to all text files found in subdirectories of the current directory.

Actual behavior

S:\play\dir-demo> Get-ChildItem -Path *.txt -Recurse -Force -Name
File.txt

Environment data

Name                           Value
----                           -----
PSVersion                      6.1.3
PSEdition                      Core
GitCommitId                    6.1.3
OS                             Microsoft Windows 10.0.17763
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

(also reproduces on inbox 5.1.17763.316)

Area-Cmdlets-Core Committee-Reviewed Issue-Question

All 9 comments

You can remove -path *.txt

PS C:\Users\mithrandir\Documents\test> gci -r -name
sub1
sub2
sub3
File.txt
sub1\File.txt
sub2\File.txt
sub3\File.txt
PS C:\Users\mithrandir\Documents\test> gci -r -name -path *.txt
File.txt

-Name should be able to use with -Path since they are not mutually exclusive. The problem appears to be here. Basically, when -Name is used, what's happening is that if the result is a directory, it will recurse into the results of matching with -Path. So maybe the fix here is in documentation. To get the behavior you want:

Get-ChildItem -Recurse -Force -Name -Include *.txt

If you want to specify a starting path to recurse:

Get-ChildItem -Recurse -Force -Name -Include *.txt -Path c:\users\slee

What would change in the documentation?

My understanding was that this

Example 3: Get child items in the current directory and subdirectories

This example displays .txt files that are located in the current directory and its
subdirectories.

PS> Get-ChildItem -Path C:\Test\*.txt -Recurse -Force
...

The Get-ChildItem cmdlet uses the Path parameter to specify C:\Test\*.txt. Path uses the
asterisk (*) wildcard to specify all files with the file name extension .txt. The Recurse
parameter searches the Path directory its subdirectories, as shown in the Directory:
headings. The Force parameter displays hidden files such as hiddenfile.txt that have a mode
of h.

combined with

-Path

Specifies a path to one or more locations. Wildcards are accepted. The default location is the
current directory (.).

implied that the pattern could be specified as the -Path parameter and would be recursed. I'm not sure I see a straightforward way to correct that (but maybe I'm just missing it).

I think the description of -Name in the documentation would be changed to reflect the current coded behavior which is when -Name is specified, the results of -Path filter is used for recursion. If you use a filter like -Path *.txt and there isn't a folder ending in .txt, no recursion will occur.

@SteveL-MSFT:

So maybe the fix here is in documentation.

I don't think that's the right fix for the baffling inconsistency of the following two commands _not_ targeting the same set of files:

# Finds *.txt files on all levels of the subtree.
Get-ChildItem -Path *.txt -Recurse 

# !! Finds *.txt files only as immediate children
Get-ChildItem -Path *.txt -Recurse -Name

Clearly, the intent of -Name is to only modify the _type_ of the objects output - (relative) path strings instead of filesystem-info objects.
That it changes _what filesystem items are targeted_ should be considered a bug.

@mklement0, I agree that the current behavior is not correct, however, the question is whether it meets our breaking change bar

Understood, but given that the current behavior is both obscure and unhelpful, it's hard to imagine that anyone actually relies on it, which makes fixing this a Bucket 3: Unlikely Grey Area change.

P.S.: It looks like -Name deserves more scrutiny:

  • 9119

  • 9120

  • 9122

  • 9126

@PowerShell/powershell-committee reviewed this, we don't believe this is a Bucket 3 item as it's likely users are relying on this in simple cases where they did not encounter the counter behavior. We agree that -Name should not change the behavior of Get-ChildItem -Recurse -Path *.txt outside of the output. However, due to the risks of the change, we propose that we should update the documentation to reflect the current behavior and pend any code change to a future FileSystemProvider v2 where -Name may not even be needed. If users want the expected behavior, use the pipeline.

Related https://github.com/PowerShell/PowerShell/issues/5785

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aragula12 picture aragula12  ยท  3Comments

SteveL-MSFT picture SteveL-MSFT  ยท  3Comments

garegin16 picture garegin16  ยท  3Comments

HumanEquivalentUnit picture HumanEquivalentUnit  ยท  3Comments

Michal-Ziemba picture Michal-Ziemba  ยท  3Comments