Search code examples
functionpowershellrecursionreturn

Powershell Recursion with Return


I am trying to write a recursive function that will return information in an array, however when I put a return statement into the function it misses certain entries.

I am trying to recursively look through a specified depth of folders getting the acl's associated with the folder. I know getChildItem has a recurse option, but I only want to step through 3 levels of folders.

The excerpt of code below is what I have been using for testing. When getACLS is called without a return statement (commented out below) the results are:

Folder 1

Folder 12

Folder 13

Folder 2

When the return statement is used I get the following output:

Folder 1

Folder 12

So it looks like the return statement is exiting out from the recursive loop?

The idea is that I want to return a multidimensional array like [folder name, [acls], [[subfolder, [permissions],[[...]]]]] etc.

cls

function getACLS ([string]$path, [int]$max, [int]$current) {

    $dirs = Get-ChildItem -Path $path | Where { $_.psIsContainer }
    $acls = Get-Acl -Path $path
    $security = @()

    foreach ($acl in $acls.Access) {
        $security += ($acl.IdentityReference, $acl.FileSystemRights)
    }   

    if ($current -le $max) {
        if ($dirs) {
            foreach ($dir in $dirs) {
                $newPath = $path + '\' + $dir.Name
                Write-Host $dir.Name
   #            return ($newPath, $security, getACLS $newPath $max ($current+1))
   #            getACLS $newPath $max ($current+1)
                return getACLS $newPath $max ($current+1)
            }   
        }
    } elseif ($current -eq $max ) {
        Write-Host max
        return ($path, $security)
    }
}

$results = getACLS "PATH\Testing" 2 0

Solution

  • The problem was the location of the return. I had it inside the foreach loop, meaning it was trying to return multiple times in the one function. I moved it outside the foreach, into the if statement instead.

    function getACLS ([string]$path, [int]$max, [int]$current) {
    
    $dirs = Get-ChildItem -Path $path | Where { $_.psIsContainer }
    $acls = Get-Acl -Path $path
    $security = @()
    $results = @()
    
    foreach ($acl in $acls.Access) {
        $security += ($acl.IdentityReference, $acl.FileSystemRights)
    }   
    
    if ($current -lt $max) {
        if ($dirs) {
            foreach ($dir in $dirs) {
                $newPath = $path + '\' + $dir.Name
                $next = $current + 1
                $results += (getACLS $newPath $max $next)
            }   
        } else {
            $results = ($path, $security)
        }
        return ($path, $security, $results)
    } elseif ($current -eq $max ) {
        return ($path, $security)
    }
    }