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
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)
}
}
In recursion, I would only use a return
statement where I needed to end the recursion - just for clarity. I've done a good bit of recursion in PowerShell and it works well. However you need to remember that PowerShell functions do behave differently. The following:
return 1,2
is equivalent to:
1,2
return
In other words, anything you don't capture in a variable or redirect to a file (or $null) is automatically considered output of the function. Here's a simple example of a working, recursive function:
function recursive($path, $max, $level = 1)
{
$path = (Resolve-Path $path).ProviderPath
Write-Host "$path - $max - $level"
foreach ($item in @(Get-ChildItem $path))
{
if ($level -eq $max) { return }
recursive $item.PSPath $max ($level + 1)
}
}
recursive ~ 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With