如何从大量文件夹中删除单个用户 ACL?
How can I remove a single user ACL from a large set of folders?
我有一个非常大的文件夹列表,我需要从每个文件夹中删除一个 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 设置回文件夹。当它到达那条线时,我得到错误
Cannot find path 'C:\Windows\system32' because it does not exist.
ACLTEST 的父文件夹中有七个文件夹,名为“01”...“07”,其中包含用于测试的各种 ACL。
我不确定从这里到哪里去。我正在阅读this Scripting Guy article这对我有很大帮助,但是他的脚本似乎专注于手动输入文件夹路径,对于需要更改的数百个文件夹我肯定做不到。
感谢任何帮助。我是 PowerShell 脚本编写的新手,所以如果您看到我在上面的脚本中提到的错误以外的任何错误,我很乐意听到它们。
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
}
我有一个非常大的文件夹列表,我需要从每个文件夹中删除一个 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 设置回文件夹。当它到达那条线时,我得到错误
Cannot find path 'C:\Windows\system32' because it does not exist.
ACLTEST 的父文件夹中有七个文件夹,名为“01”...“07”,其中包含用于测试的各种 ACL。
我不确定从这里到哪里去。我正在阅读this Scripting Guy article这对我有很大帮助,但是他的脚本似乎专注于手动输入文件夹路径,对于需要更改的数百个文件夹我肯定做不到。
感谢任何帮助。我是 PowerShell 脚本编写的新手,所以如果您看到我在上面的脚本中提到的错误以外的任何错误,我很乐意听到它们。
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
}