Identifying NTFS Folder Permission Differences

This topic contains 7 replies, has 5 voices, and was last updated by Profile photo of Rob Simmers Rob Simmers 1 year, 3 months ago.

  • Author
  • #27314
    Profile photo of David Tobias
    David Tobias

    I've taken on the task of doing folder/file cleanup on our NAS and I've run into a scenario where I'm definitely thinking that Powershell can really help. To note, my PS experience is limited at best. I'm familair with some of the AD/Office 365 cmdlets from my daily tasks but do not have a ton of experience when creating advanced scripts.

    I have a parent folder on our NAS with a large amount of access entries on it. This parent folder has hundreds of subfolders. I'm doing some organization of the access entries, but over the years, inheritance has been broken on several subfolders and ACLs have been changed. I'd like to develop a script (or be pointed towards a good resource) that I can recursively run against my parent folder and get a list of subfolders where the ACL is different than that of the parent folder.

    I'm thinking that I can leverage both the Get-ChildItem and Get-Acl cmdlets to accomplish what I want but I'm having some difficulty in bringing it all together.

    I appreciate any advice that you can share with me or resources that you can point me to.

    Thank you!

  • #27315
    Profile photo of Don Jones
    Don Jones

    Get-ACL will get you a permission object; I'd get it from the parent and store it in a variable.

    From there, Get-ChildItem can get you the child folders, which can be piped to Get-ACL to get their permission object. I'd probably do that in a loop.

    $parent_acl = get-cal c:\parent
    foreach ($folder in (get-childitem c:\parent -directory -recurse)) {
      $folder_acl = get-acl $folder
      compare-object $parent_acl $folder_acl

    That – or something similar – will give you a difference object for each child whose ACL is different from the parent's.

    But... Get-ACL only shows direct ACEs, not inherited ones. So a child folder with no ACEs will show as "different" from the parent, because it's inheriting from the parent, which is in fact what you wanted. So in that case, "different" is good, not bad.

    It might be worth thinking carefully about what, exactly, you want to look at and mitigate, before you go down the path of a lot of coding.

  • #27329
    Profile photo of Deepak

    Hey Don ....Nice logic and code. Awesome...
    Just wanted to understand David's requirement here..
    Do you want the script to ask for a path of folder and should match the ACL with its parent folder ?

  • #27346
    Profile photo of David Tobias
    David Tobias

    Thank you, Don. Really like how this came together. doesn't necessarily need to prompt for a folder path. I can supply the top level parent directory. I'm just looking for it to recursively move through all of the subfolders and determine the difference between each one of them against what the ACLs on the top level parent folder are.

  • #27366
    Profile photo of Rohn Edwards
    Rohn Edwards

    What about something like this?

    Get-ChildItem C:\folder -Recurse | ForEach-Object {
        try { # Get-Acl throws terminating errors, so wrap it in a try/catch block
            $_ | Get-Acl | 
                where { $_.AreAccessRulesProtected -or ($_.Access | where { $_.IsInherited -eq $false }) } |
                foreach { Convert-Path $_.Path }
        catch {
            Write-Error $_

    That should return the path to any files/folders (depends on how you call Get-ChildItem) where DACL inheritance is disabled or a single non-inherited ACE is present. It would be a much prettier command if Get-Acl handled errors properly and you didn't have to put it in that ForEach-Object block...

    With a little tweaking, you could get it to show you the differences instead of just giving you the paths.

  • #27449
    Profile photo of Deepak

    Just created below one. The script might not be clean :(..The number of lines in code can be reduced. But I just started with PS.

    The script will check if inheritance is broken in any directories and list the ACL of current and its parent. I am not sure if it helps you.

    I am looking for the suggestions from experienced guys to get this cleaned ...Thanks..

    # Give the path of directory below
    $DirDetails = Get-ChildItem -path C:\Work\Test -Recurse -Attributes Directory
    ForEach ($Dir in $DirDetails) {
    $DirFullName = $Dir.FullName
    $DirName = $Dir.Name
    $Acl = Get-Acl $DirFullName
    $AclAccess = $Acl.Access
    $InheritedList = $AclAccess.Isinherited
    [int]$BadFolderCount = "0"
    foreach ($ISInherit in $InheritedList) {
    If ($ISInherit -like "False") {
    If ($BadFolderCount -gt "0") {
    Write-Host "Directory Name                      :$DirFullName" -ForegroundColor Red
    Write-Host "Count of Not Inherited ACLs         :$BadFolderCount" -ForegroundColor Red
    Write-Host ""
    Write-Host "ACL of Current Directory            :"
    (Get-Acl $DirFullName).Access | select FileSystemRights , IdentityReference | fl
    Write-Host "ACL of Parent Directory             :"
    (Get-Acl ($DirFullName.TrimEnd($DirName))).Access | select FileSystemRights , IdentityReference | fl
    Else {
    Write-Host "Directory Name                      :$DirFullName" -ForegroundColor Green
    Write-Host "Count of Not Inherited ACLs         :$BadFolderCount" -ForegroundColor Green
    Write-Host ""
  • #27450
    Profile photo of Deepak

    By the way Rohn Edwards , wonderful code.
    PS code should be like this. Short and powerful 🙂

  • #27454
    Profile photo of Rob Simmers
    Rob Simmers

    Try this:

    $DirDetails = Get-ChildItem -path C:\Temp\* -Recurse -Attributes Directory
    $Acls = ForEach ($Dir in $DirDetails) {
        Get-Acl $Dir.FullName |
            Select Owner,
                   @{Name="Non-Inherited Perms";Expression={($_.Access | Where{$_.IsInherited -eq $false}) | foreach{"{0}: {1}" -f $_.IdentityReference, $_.FileSystemRights}}},
                   @{Name="Non-Inherited Count";Expression={($_.Access | Where{$_.IsInherited -eq $false}).Count}},

    Your script is using Write-Host, which isn't a good practice to begin with. The Power of Powershell comes from working with objects. In your script, you're just writing information to the prompt, which tells you what is wrong but you have to dig thru output to understand how many directories have non-inherited permissions. If I use the script I posted, I just have to do a simple query to see what folder are not set the way I want:

    $Acls | Where{$_."Non-Inherited Count" -gt 0}

    Additionally, if I want to fix them, it's a simple as:

    $Acls | Where{$_."Non-Inherited Count" -gt 0} | foreach{
        Set-ACL $_.DirFullName ...

    So, I highly recommend trying to keep your data in an object versus writing it in colors to the screen.

You must be logged in to reply to this topic.