Powershell – Get-ChildItem for 2-3 levels

powershell

So, I'm trying to pull a listing of the DFS-N folder structure for a client. However, for various reasons I'm going to be limiting it to 2 levels deep from $share. Also, the 40+ file servers don't have PowerShell 5 yet, so using the -depth switch isn't an option right now.

The problem I'm having is that the method I read should limit it, isn't limiting it correctly.

Get-ChildItem -path $share,$share\*,$share\*\* | ForEach-Object {
        $Path  = "$_"

        $Acl = Get-Acl $Path
        $Acl | 
            Select-Object -ExpandProperty Access | 
            Add-Member -MemberType NoteProperty -Name Path -Value $Path -PassThru  |
            Add-Member -MemberType NoteProperty -Name Owner -Value $Acl.Owner -PassThru

However, when I look at the output, it contains what appears to be every single folder under $path, some of which are 3 levels deep, not just 2. It's not a huge issue, but I'm wondering if anyone knows what I'm doing wrong? As an example, $share is being defined as:

$share = "\\" + $server + "\" + $site + "_Data"

But I'm seeing results that are like, for example: \\namespace\site_data\SOX\Activo Fijo 2016\Septiembre

Best Answer

How about manually grabbing the first level only, then looping though the second level as a step? I made your code to print the ACLs into a function, and manually stepped through grabbing the first three levels. If the items in the first level are folders ($_.ISPSContainer), they get their child items pulled and processed, and another level of the same to get the next level. Ideally, you wouldn't re-use the code, it should be refactored into another function to do the recursion, but that would require passing a parameter that you could tell it how many more levels to pull. Then each loop could decrement that counter and call itself if the $counter -gt 0.

Function Print-Acl {
    param(  
    [Parameter(
        Position=0, 
        Mandatory=$true)
    ]
    [String[]]$Path
    ) 

    $Acl = Get-Acl $Path
    $Acl | 
        Select-Object -ExpandProperty Access | 
        Add-Member -MemberType NoteProperty -Name Path -Value $Path -PassThru  |
        Add-Member -MemberType NoteProperty -Name Owner -Value $Acl.Owner -PassThru
}

Get-ChildItem -path $share | ForEach-Object {
    # First Level
    if ($_.PSIsContainer) {
        Print-Acl -Path $_.FullName
        Get-ChildItem -Path $_.FullName | ForEach-Object {
            # Second Level
            if ($_.PSIsContainer) {
                # Third level
                Print-Acl -Path $_.FullName
                Get-ChildItem -Path $_.FullName | ForEach-Object {
                    Print-Acl -Path $_.FullName
                }
            }
            else {
                Print-Acl -Path $_.FullName
            }
        }
    }
    else {
        Print-Acl -Path $_
    }
}