【问题标题】:How can I remove a single user ACL from a large set of folders?如何从大量文件夹中删除单个用户 ACL?
【发布时间】:2015-12-05 22:35:52
【问题描述】:

我有一个非常大的文件夹列表,我需要从每个文件夹中删除一个 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
}

根据我在调试期间看到的情况,我认为一切正常,直到我尝试将 ACL 设置回文件夹。当它到达那条线时,我得到了错误

找不到路径“C:\Windows\system32\01”,因为它不存在。

在 ACLTEST 的父文件夹内有七个文件夹,名为“01”...“07”,带有用于测试的各种 ACL。

我不知道从这里去哪里。我正在阅读this Scripting Guy article,这对我有很大帮助,但他的脚本似乎专注于手动输入文件夹路径,对于需要更改的数百个文件夹,我绝对不能这样做。

感谢任何帮助。我是 PowerShell 脚本的新手,所以如果您发现除了我在上面脚本中提到的错误之外的任何错误,我很想听听。

【问题讨论】:

    标签: powershell powershell-2.0 acl powershell-3.0


    【解决方案1】:

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

    改变

    Set-Acl -Path $folder -AclObject $acl
    

    进入

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

    问题就会消失。

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

    $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)]
    

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

    $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
            }
        }
    }
    

    每个访问规则只有一个身份引用,所以内部循环是没有意义的。

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

    你的代码可以简化成这样:

    $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
    }
    

    或(使用管道)像这样:

    $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
    }
    

    【讨论】:

    • 非常感谢!这正是我正在寻找的,因为我知道我的代码可能不是最好的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多