Recursive Directory Traversal to a Specific Depth in PowerShell29 Apr 2020 · Comments: 0 · Tags: PowerShell
function acts as a wrapper around
Get-ChildItem facilitating recursive
traversal of a path to a specific depth. Whilst what’s covered should be
agnostic, I’ll be focusing specifically on file system directories.
Although the function serves a single purpose, behind the scenes the implementation differs depending on whether the PowerShell version is pre-5.0 or 5.x, read on for details.
PowerShell Prior to 5.0
Prior to PowerShell 5.0,
Get-ChildItem had no built-in method to limit
recursive traversal of a path to a specific depth. The Get-ChildItemToDepth
function achieves this through the use of a recursive function (a function that
calls itself). The recursion logic is a derivative work based on this code snippet
written by Chris Dent.
As at the time of writing this post (April 2020), all supported versions of Windows are capable of running PowerShell 5.x. Consequently I don’t tend to encounter anything older than PowerShell 4.0 (the stock version of PowerShell on Windows Server 2012 R2), so that’s all I’ve had the opportunity to test this function against. However, I see no reason for it not to work on even older versions of PowerShell.
In PowerShell 5.0, the
Get-ChildItem cmdlet gained a
enabling a path to be recursively traversed to a specific depth. Unfortunately
in PowerShell 5.x the
-Depth parameter has a peculiar quirk that’s exhibited
when used against a legitimate path containing one or more wildcard characters.
It results in recursive traversal of the entire directory tree.
NB: This behaviour has since been rectified in PowerShell 6.0.
To illustrate the problem, I recursively traversed
(the question mark is a wildcard denoting a single character) with no depth
-Recurse) and with a depth limit of two (
-Depth 2), using PowerShell
5.1 and 6.0.1 on the same machine. See how in PowerShell 5.1 count returns the
same value in both cases.
To overcome this issue, Get-ChildItemToDepth
offloads responsibility for expanding a path containing wildcards from
Resolve-Path and passes the result(s) to
Get-ChildItem -LiteralPath <path> -Depth <n>.
-LiteralPath parameter is used to avoid the expansion of literal wildcard
characters in file and directory names.
See example below, it recursively traverses
"C:\Test\Sub*" to a depth of two,
returning files with the extension
XLSX. I’ve deliberately included a
subdirectory with square brackets in the name (
SubB) just to highlight why
-LiteralPath behind the scenes.