How to Recursively Reset NTFS Permissions in Windows Using Command Line and PowerShell


2 views

We've all been there - inheriting a massive directory structure with broken NTFS permissions where someone went wild with the security settings. Random deny entries, incorrect ownership, and dangerous "Everyone" permissions scattered throughout the tree. When you need to completely reset permissions to a known good state across thousands of files and folders, manual fixes just won't cut it.

For Unix admins, this would be a simple chown -R and chmod -R operation. In Windows, we have two powerful tools:

# Command Line version using ICACLS
icacls "C:\ProblemFolder" /reset /T /C /Q

# PowerShell equivalent
Get-ChildItem "C:\ProblemFolder" -Recurse | ForEach-Object {
    icacls $_.FullName /reset /Q
}

The magic happens with ICACLS's /reset parameter which:

  • Removes all explicit permissions
  • Sets inherited permissions from parent
  • Preserves the SYSTEM account permissions

If you're getting "Access Denied" errors, you'll need to take ownership first:

takeown /F "C:\ProblemFolder" /R /A /D Y
icacls "C:\ProblemFolder" /grant:r Administrators:(OI)(CI)F /T

For more granular control than just resetting to inherited, you can define explicit permissions:

# Grant full control to Admin, modify to Users, read to Everyone
icacls "C:\SecureData" /inheritance:r /grant:r
    "Administrators:(OI)(CI)F" /grant:r
    "Users:(OI)(CI)M" /grant:r
    "Everyone:(OI)(CI)R" /T

For production use, consider this robust function:

function Reset-NTFSPermissions {
    param(
        [string]$Path,
        [string]$User = "$env:USERDOMAIN\$env:USERNAME",
        [bool]$ResetInheritance = $true
    )
    
    $acl = Get-Acl $Path
    if ($ResetInheritance) {
        $acl.SetAccessRuleProtection($false, $true)
    }
    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        $User, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
    )
    $acl.SetAccessRule($rule)
    Set-Acl -Path $Path -AclObject $acl
    
    Get-ChildItem $Path -Recurse | ForEach-Object {
        try {
            $acl = Get-Acl $_.FullName
            if ($ResetInheritance) {
                $acl.SetAccessRuleProtection($false, $true)
            }
            $acl.SetAccessRule($rule)
            Set-Acl -Path $_.FullName -AclObject $acl
        } catch {
            Write-Warning "Failed to process $($_.FullName): $_"
        }
    }
}

For system directories or stubborn objects:

  • Use /B with takeown for backup privilege
  • Processes like TrustedInstaller may need special handling
  • Consider using subinacl for complex scenarios

Always verify permissions after bulk operations:

icacls "C:\TargetFolder" /save permfile.txt /T
notepad permfile.txt

We've all encountered those messy NTFS permission structures - inherited permissions broken, random ACEs assigned, or Everyone having write access to sensitive directories. When you inherit a system with a deep directory tree (like a migrated file server or legacy application), manually fixing permissions through the GUI becomes impossible.

Coming from Unix where chmod -R and chown -R solve permission problems elegantly, Windows administrators often miss equivalent tools. The key Windows utilities we'll use:

icacls - The modern replacement for cacls
takeown - For ownership changes
robocopy - For permission mirroring

For a complete permission rebuild (use with caution!):

takeown /F "C:\ProblemPath" /R /D Y
icacls "C:\ProblemPath" /reset /T /C /Q
icacls "C:\ProblemPath" /grant:r "DOMAIN\YourUser:(OI)(CI)F" /T /C /Q

This sequence:

  1. Takes ownership of everything
  2. Clears all existing permissions
  3. Grants full control to your account

For specific permission scenarios:

:: Remove all Everyone entries
icacls "C:\Path" /remove:g Everyone /T /C

:: Set read-only for Users group
icacls "C:\Path" /grant:r "BUILTIN\Users:(OI)(CI)(RX)" /T

:: Copy permissions from a known-good location
robocopy "C:\GoodTemplate" "C:\ProblemPath" /E /COPYALL /SEC /SECFIX /MIR /XJ

To enable/disable inheritance:

:: Disable inheritance (copy existing permissions)
icacls "C:\Path" /inheritance:d

:: Re-enable inheritance (from parent)
icacls "C:\Path" /inheritance:e

For consistent permission structures, save and apply templates:

:: Export permissions
icacls "C:\TemplateFolder" /save "C:\perms.txt" /T /C

:: Apply saved permissions
icacls "C:\TargetFolder" /restore "C:\perms.txt"

For more granular control:

# Recursive permission reset
Get-ChildItem -Path "C:\Path" -Recurse | ForEach-Object {
    $acl = Get-Acl $_.FullName
    $acl.SetAccessRuleProtection($true, $false)
    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        "DOMAIN\User","FullControl","ContainerInherit,ObjectInherit","None","Allow")
    $acl.AddAccessRule($rule)
    Set-Acl -Path $_.FullName -AclObject $acl
}
  • Always test in non-production first
  • System files may require TrustedInstaller permissions
  • Watch for long path name issues (>260 chars)
  • Consider creating a rollback script before mass changes