diff --git a/src/System.Management.Automation/engine/SessionStateContainer.cs b/src/System.Management.Automation/engine/SessionStateContainer.cs
index 97c412f3f0e..efcc2feedc3 100644
--- a/src/System.Management.Automation/engine/SessionStateContainer.cs
+++ b/src/System.Management.Automation/engine/SessionStateContainer.cs
@@ -1593,7 +1593,7 @@ internal void GetChildItems(
}
int unUsedChildrenNotMatchingFilterCriteria = 0;
- ProcessPathItems(providerInstance, providerPath, recurse, context, out unUsedChildrenNotMatchingFilterCriteria, ProcessMode.Enumerate);
+ ProcessPathItems(providerInstance, providerPath, recurse, depth, context, out unUsedChildrenNotMatchingFilterCriteria, ProcessMode.Enumerate);
}
}
else
@@ -1861,6 +1861,72 @@ private void ProcessPathItems(
out int childrenNotMatchingFilterCriteria,
ProcessMode processMode = ProcessMode.Enumerate,
bool skipIsItemContainerCheck = false)
+ {
+ // Call ProcessPathItems with 'depth' set to maximum value for infinite recursion when needed.
+ ProcessPathItems(providerInstance, path, recurse, uint.MaxValue, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck);
+ } // ProcessPathItems
+
+ ///
+ /// Since we can't do include and exclude filtering on items we have to
+ /// do the recursion ourselves. We get each child name and see if it matches
+ /// the include and exclude filters. If the child is a container we recurse
+ /// into that container.
+ ///
+ ///
+ ///
+ /// The instance of the provider to use.
+ ///
+ ///
+ ///
+ /// The path to the item to get the children from.
+ ///
+ ///
+ ///
+ /// Recurse into sub-containers when getting children.
+ ///
+ ///
+ ///
+ /// Limits the depth of recursion; uint.MaxValue performs full recursion.
+ ///
+ ///
+ ///
+ /// The context under which the command is running.
+ ///
+ ///
+ ///
+ /// The count of items that do not match any include/exclude criteria.
+ ///
+ ///
+ /// Indicates if this is a Enumerate/Remove operation
+ ///
+ /// a hint used to skip IsItemContainer checks
+ ///
+ ///
+ /// If the refers to a provider that could not be found.
+ ///
+ ///
+ ///
+ /// If the refers to a drive that could not be found.
+ ///
+ ///
+ ///
+ /// If the provider that the refers to does
+ /// not support this operation.
+ ///
+ ///
+ ///
+ /// If the provider threw an exception.
+ ///
+ ///
+ private void ProcessPathItems(
+ CmdletProvider providerInstance,
+ string path,
+ bool recurse,
+ uint depth,
+ CmdletProviderContext context,
+ out int childrenNotMatchingFilterCriteria,
+ ProcessMode processMode = ProcessMode.Enumerate,
+ bool skipIsItemContainerCheck = false)
{
ContainerCmdletProvider containerCmdletProvider = GetContainerProviderInstance(providerInstance);
childrenNotMatchingFilterCriteria = 0;
@@ -2016,7 +2082,7 @@ private void ProcessPathItems(
}
// Now recurse if it is a container
- if (recurse && IsPathContainer(providerInstance, qualifiedPath, context))
+ if (recurse && IsPathContainer(providerInstance, qualifiedPath, context) && depth > 0)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
@@ -2024,7 +2090,7 @@ private void ProcessPathItems(
return;
}
// The item is a container so recurse into it.
- ProcessPathItems(providerInstance, qualifiedPath, recurse, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck: true);
+ ProcessPathItems(providerInstance, qualifiedPath, recurse, depth - 1, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck: true);
}
} // for each childName
}
@@ -2066,7 +2132,6 @@ private void ProcessPathItems(
}
} // ProcessPathItems
-
///
/// Gets the dynamic parameters for the get-childitem cmdlet.
///
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-ChildItem.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-ChildItem.Tests.ps1
index 043b9c4c6f9..1956a558f9f 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-ChildItem.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-ChildItem.Tests.ps1
@@ -9,13 +9,15 @@ Describe "Get-ChildItem" -Tags "CI" {
$item_c = "c283d143-2116-4809-bf11-4f7d61613f92"
$item_D = "D39B4FD9-3E1D-4DD5-8718-22FE2C934CE3"
$item_E = "EE150FEB-0F21-4AFF-8066-AF59E925810C"
- $item_F = ".F81D8514-8862-4227-B041-0529B1656A43"
+ $item_F = ".F81D8514-8862-4227-B041-0529B1656A43"
+ $item_G = "5560A62F-74F1-4FAE-9A23-F4EBD90D2676"
$null = New-Item -Path $TestDrive -Name $item_a -ItemType "File" -Force
$null = New-Item -Path $TestDrive -Name $item_B -ItemType "File" -Force
$null = New-Item -Path $TestDrive -Name $item_c -ItemType "File" -Force
$null = New-Item -Path $TestDrive -Name $item_D -ItemType "File" -Force
$null = New-Item -Path $TestDrive -Name $item_E -ItemType "Directory" -Force
$null = New-Item -Path $TestDrive -Name $item_F -ItemType "File" -Force | ForEach-Object {$_.Attributes = "hidden"}
+ $null = New-Item -Path (Join-Path -Path $TestDrive -ChildPath $item_E) -Name $item_G -ItemType "File" -Force
}
It "Should list the contents of the current folder" {
@@ -66,6 +68,18 @@ Describe "Get-ChildItem" -Tags "CI" {
$file.Count | Should be 1
$file.Name | Should be $item_F
}
+
+ It "Should list items in current directory only with depth set to 0" {
+ (Get-ChildItem -Path $TestDrive -Depth 0).Count | Should Be 5
+ (Get-ChildItem -Path $TestDrive -Depth 0 -Include *).Count | Should Be 5
+ (Get-ChildItem -Path $TestDrive -Depth 0 -Exclude IntentionallyNonexistent).Count | Should Be 5
+ }
+
+ It "Should return items recursively when using 'Include' or 'Exclude' parameters" {
+ (Get-ChildItem -Path $TestDrive -Depth 1).Count | Should Be 6
+ (Get-ChildItem -Path $TestDrive -Depth 1 -Include $item_G).Count | Should Be 1
+ (Get-ChildItem -Path $TestDrive -Depth 1 -Exclude $item_a).Count | Should Be 5
+ }
}
Context 'Env: Provider' {