Logo
Getting Files and Folders Recursively in PowerShell Without Using -Recurse
PowerShell

Getting Files and Folders Recursively in PowerShell Without Using -Recurse

7 August 2020 By Hal Sclater

This is a PowerShell script which will traverse a directory structure listing all files and folders, without using the built-in -Recurse switch.

PowerShell has a built-in switch for this using Get-ChildItem C:\temp -Recurse. However, this script shows how to do it using a recursive function instead — useful for understanding the logic and applying it to other languages that may not have a recurse switch.

The script works by getting the child files and folders, then if it finds a folder it calls itself.

function Get-FolderTree {
    param (
        [Parameter(Mandatory)]
        [string]$Path
    )

    foreach ($item in Get-ChildItem -LiteralPath $Path) {
        if ($item.PSIsContainer) {
            Write-Host $item.FullName -ForegroundColor Blue
            $item.FullName
            Get-FolderTree -Path $item.FullName   # Recurse into the directory
        }
        else {
            Write-Host $item.FullName -ForegroundColor Yellow
            $item.FullName
        }
    }
}

$subfolders = Get-FolderTree -Path "C:\Temp"

The key detail is that the function emits the path instead of appending to an array. Anything written to the output stream is collected by the caller, so a recursive call automatically returns its results to the level above it.

Don’t do this: $array += $fullpath inside the function. In PowerShell that creates a new local variable on every call, so each recursive call builds its own array and the results are thrown away when it returns. The script appears to run but returns an incomplete list. If you do want to accumulate into an array, declare it outside the function and use $script:array, or pass a [System.Collections.Generic.List[string]] in as a parameter.

The script outputs folders in blue and files in yellow, making it easy to distinguish between them at a glance. Because $subfolders captures everything the function emitted, it contains every file and folder in the tree — the same output you’d get from Get-ChildItem -Path "C:\Temp" -Recurse, but spelled out so the logic is visible.