Today my wife told me about a problem on the family PC.  There were a bunch of PDF files in a directory that had the wrong permissions so my son couldn’t access them.  She modified the ACL on one of them using Explorer and verified that that was the fix.  (This is from a test I ran)


She then selected them all and tried to do it all at once but when she brought up the Properties, it didn’t have the Security Page anymore:


She wanted to know if there was some trick to set the ACLs all at once.  I told her that PowerShell could do that.  I showed her how to use Get-Acl and Set-Acl and she gave me a look like, “you expect me to remember that?” and asked, “why don’t you just have a COPY-ACL’ cmdlet.  I told her her how “to ship is to choose” but she wasn’t having any of it.  She clearly thought I was an idiot for not having shipped Copy-Acl.  You know what – I totally get it.  As a user – who cares how tough it is to ship software at Microsoft?  All that matters is that you have a need and we either meet it or we don’t.  Sadly that doesn’t change the reality of what it takes to ship things at Microsoft but it does provide some energy to write/share scripts.

As such, I spent a few minutes and wrote Copy-Acl.  I hope you enjoy it.  I’ve also attached it as a file to this blog. 


Jeffrey Snover [MSFT]
Distinguished Engineer
Visit the Windows PowerShell Team blog at:
Visit the Windows PowerShell ScriptCenter at:




Copy the ACL from one file to other files

Takes a file and copies its ACL to one or more other files.

Path of the File to get the ACL from.

.PARAMETER Destination
Path to one or more files to copy the ACL to.

Returns an object representing the security descriptor.  By default, this cmdlet does not generate any output.

You can Pipeline any object with a Property named "PSPath", "FullName" or "Destination".

PS> Copy-Acl Referencefile.txt (dir c:\temp\*xml)

PS> dir c:\files *.xml -recurse | Copy-Acl ReferenceFile.txt


Author:  Jeffrey Snover

#requires -Version 2.0


    if (! (Test-Path $FromPath))
        $ErrorRecord = New-Object System.Management.Automation.ErrorRecord  (
            (New-Object Exception "FromPath ($fromPath) does not point to an existing object"),

    $acl = Get-Acl $FromPath
    foreach ($Dest in @($Destination))
        if ($pscmdlet.ShouldProcess($Dest))
            Set-Acl -Path $Dest -AclObject $acl -Passthru:$PassThru