如何从大量文件夹中删除单个用户ACL?

Mic*_*l H 4 powershell acl powershell-2.0 powershell-3.0

我有一个非常大的文件夹列表,我需要从每个文件夹中删除一个ACL.而不是手动完成,我试图编写一个脚本来在很短的时间内完成它,但我遇到了一些麻烦.

这是我到目前为止:

$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
}
Run Code Online (Sandbox Code Playgroud)

从我在调试期间看到的内容来看,我认为一切正常,直到我尝试将ACL设置回文件夹.当它到达那一行时,我得到了错误

找不到路径'C:\ Windows\system32\01',因为它不存在.

在ACLTEST的父文件夹中有七个名为"01"的文件夹..."07",其中包含各种用于测试的ACL.

我不知道从哪里开始.我正在阅读这篇脚本专家文章,它帮助了我很多,但他的脚本似乎专注于手动输入文件夹路径,我绝对不能为需要更改的几百个文件夹做.

任何帮助表示赞赏.我是PowerShell脚本的新手,所以如果你看到上述脚本中我所指的任何错误,我很乐意听到它们.

Ans*_*ers 7

期望路径字符串的-Path参数Set-Acl,而不是DirectoryInfo对象.当传递后者时,只Name扩展其属性,因此Set-Acl在当前工作目录中查找具有给定名称的对象(在您的情况下显然C:\Windows\system32).

更改

Set-Acl -Path $folder -AclObject $acl
Run Code Online (Sandbox Code Playgroud)

Set-Acl -Path $folder.FullName -AclObject $acl
Run Code Online (Sandbox Code Playgroud)

问题就会消失.

话虽如此,您可能还想进行一些其他修改.

$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)]
Run Code Online (Sandbox Code Playgroud)

如果您不想要数组中的父文件夹:首先不要将它放在数组中.由于您显然拥有PowerShell v3,因此您可以使用-Directory参数而不是where过滤器.

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

每个访问规则只有一个标识引用,因此内部循环是没有意义的.

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

您的代码可以简化为以下内容:

$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
}
Run Code Online (Sandbox Code Playgroud)

或者(使用管道)像这样:

$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
}
Run Code Online (Sandbox Code Playgroud)