How can I remove a single user ACL from a large set of folders?

最后都变了- 提交于 2019-12-10 17:35:35

问题


I have a very large list of folders and I need to remove a single ACL from each of them. Rather than doing it manually, I'm trying to write a script to do it in a fraction of the time, but I'm running into a bit of trouble.

Here is what I have so far:

$filepath = "C:\ALCTEST"
$user = "domain\username"

$folders = @((get-item $filePath))
$folders += Get-ChildItem $filePath -Recurse |
            where { $_.PSIsContainer -ne $false }

##Need to do this in order to remove item 0 from the array, otherwise
##item 0 is the parent folder
$newfolders = $folders[1,2 + 3..($folders.length - 1)]

foreach ($folder in $newfolders) {
    $acl = Get-Acl -Path $folder.FullName

    foreach ($access in $acl.access) {
        foreach ($value in $access.IdentityReference.Value) {
            if ($value -eq $user) {
                $acl.RemoveAccessRule($access) | Out-Null
            }
        }
    }

    Set-Acl -Path $folder -AclObject $acl
}

From what I watched during the debug, I think everything works right up until I try to set the ACL back onto the folders. When it gets to that line, I get the error

Cannot find path 'C:\Windows\system32\01' because it does not exist.

Inside the parent folder of ACLTEST are seven folders named "01"..."07" with various ACLs for testing.

I'm not sure where to go from here. I was reading this Scripting Guy article which helped me through a lot, but his script seems to be focused on manually entering folder paths, which I definitely can't do for the several hundred folders that need to be changed.

Any help is appreciated. I'm new to PowerShell scripting, so if you see any mistakes other than what I'm referring to in the script above, I'd love to hear them.


回答1:


The -Path parameter of Set-Acl expects a path string, not a DirectoryInfo object. When passing the latter only its Name property is expanded, so Set-Acl is looking for an object with the given name in the current working directory (in your case apparently C:\Windows\system32).

Change

Set-Acl -Path $folder -AclObject $acl

into

Set-Acl -Path $folder.FullName -AclObject $acl

and the problem will disappear.

With that said, you may want to make some other modifications as well.

$folders = @((get-item $filePath))
$folders += Get-ChildItem $filePath -Recurse |
            where { $_.PSIsContainer -ne $false }

##Need to do this in order to remove item 0 from the array, otherwise
##item 0 is the parent folder
$newfolders = $folders[1,2 + 3..($folders.length - 1)]

If you don't want the parent folder in the array: don't put it in the array in the first place. And since you apparently have PowerShell v3, you could use the -Directory parameter instead of a where filter.

$newfolders = Get-ChildItem $filePath -Recurse -Directory
foreach ($access in $acl.access) {
    foreach ($value in $access.IdentityReference.Value) {
        if ($value -eq $user) {
            $acl.RemoveAccessRule($access) | Out-Null
        }
    }
}

Each access rule has only a single identity reference, so the inner loop is pointless.

foreach ($access in $acl.access) {
    if ($access.IdentityReference.Value -eq $user) {
        $acl.RemoveAccessRule($access) | Out-Null
    }
}

Your code could be streamlined to something like this:

$filepath = 'C:\ALCTEST'
$user     = 'domain\username'

$folders = Get-ChildItem $filePath -Recurse -Directory

foreach ($folder in $folders) {
    $acl = Get-Acl -Path $folder.FullName

    foreach ($access in $acl.Access) {
        if ($access.IdentityReference.Value -eq $user) {
            $acl.RemoveAccessRule($access) | Out-Null
        }
    }

    Set-Acl -Path $folder.FullName -AclObject $acl
}

or (using pipelines) like this:

$filepath = 'C:\ALCTEST'
$user     = 'domain\username'

Get-ChildItem $filePath -Recurse -Directory | ForEach-Object {
    $acl = Get-Acl -Path $_.FullName

    $acl.Access | Where-Object {
        $_.IdentityReference.Value -eq $user
    } | ForEach-Object {
        $acl.RemoveAccessRule($_) | Out-Null
    }

    Set-Acl -Path $_.FullName -AclObject $acl
}


来源:https://stackoverflow.com/questions/32488342/how-can-i-remove-a-single-user-acl-from-a-large-set-of-folders

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!