Search code examples
powershelltreetreeviewntfs

Folder Tree with NTFS Permissions


I'm trying to build a little script with PowerShell, but I'm stuck.

I need to give out the structure of a folder as a tree with its NTFS permissions.

C:\TEST
├───Test1 - Access
│   ├───Test1.1 - Access
│   └───Test1.2 - Access
│       └───Test1.2.1 - Access
├───Test2 - Access
│   ├───Test2.1 - Access
│   └───Test2.2 - Access
├───Test3 - Access
└───Test4 - Access
    ├───Test4.1 - Access
    ├───Test4.2 - Access
    └───Test4.3 - Access

Something like this.

I tried with Get-ChidlItem C:\Test -Recurse and Get-Acl, but I couldn't figure out how to display the results as a tree.


Solution

  • Below is a script that I wrote recently to output a directory structure as a tree with file sizes to the console.

    You can easily modify the Write-Host lines to remove the file sizes and add in your ACL information (I'm not really sure aesthetically how this will work).

    The big limitation of using Write-Host is that you can't work with the data further down the script, you can't output the data to a file - Start-Transcript loses the formatting.

    Jacob Colvin's comments descript a much better approach, something I would be interested to see in practice.

    The only other approach I could think of, would be to create an object which combines the Get-ACL and Get-ChildItem data, and then when outputting the data, counting the \'s in the directory structure to generate the indentation.

    function Show-Tree
    {
        param
        (
            $directory
        )
        if ((Get-PSCallStack)[1].Command -eq 'Show-Tree') {
            Write-host "├──" -NoNewline
            if(Test-Path $directory/*)
            {
                Write-host "┬" -NoNewline
            }
            else
            {
                Write-host "─" -NoNewline
            }
            Write-Host "$($directory | Split-Path -Leaf)/"
        }
        else
        {
            Write-Host "$directory"
            $Script:StartingIndent = ($directory).Split("\").Count+1
        }
        Get-ChildItem -path $directory -File | % { 
            $i = 0
            $indent = ($_.FullName).Split("\").Count-$script:StartingIndent
            while($i -lt $indent)
            {
                [console]::Write("│  ")
                $i++
            }
            if(($_.length / 1MB) -ge 1)
            {
                Write-Host "├───[$([int]($_.length / 1MB)) MB] $($_.name)"
            }
            elseif(($_.length / 1KB -ge 1))
            {
                Write-Host "├───[$([int]($_.length / 1KB)) KB] $($_.name)"
            }
            else
            {
                Write-Host "├───[$($_.length) B] $($_.name)"
            }
        }
        Get-ChildItem -Path $directory -Directory | % {
            $i = 0
            $indent = ($_.FullName).Split("\").Count-$script:StartingIndent
            while($i -lt $indent)
            {
                Write-host "│  " -NoNewline
                $i++
            }
            Show-Tree -directory $_.FullName
        }
    }
    
    Show-Tree -directory C:\Testing
    

    Output

    C:\Testing
    ├───[7 KB] $RY3NETI.prop
    ├───[9 KB] Book1.xlsx
    ├───[308 B] csvOut.csv
    ├───[308 B] csvOut2.csv
    ├───[297 B] csvout3.csv
    ├───[6 MB] Shakespear.txt
    ├───[570 KB] ShakeSpeareUniqueWords.txt
    ├───[1 KB] Transcript.txt
    ├──┬Test1/
    │  ├───[183 B] filename.rtf
    │  ├───[7 KB] img3.png
    │  ├───[18 KB] img4.png
    │  ├───[43 KB] img5.png
    │  ├───[19 KB] img7.png
    │  ├───[26 KB] test.doc
    ├──┬Test2/
    │  ├───[83 MB] filetest.rar
    │  ├───[7 KB] img10.png
    │  ├───[18 KB] img9.png
    │  ├──┬Test2 Subfolder/
    │  │  ├───[33 KB] img1.png
    │  │  ├───[17 KB] img2.png
    │  │  ├───[14 KB] img8.png