运行ACL脚本添加安全组,如何跳过继承已禁用文件夹的子项?
问题原因
你的脚本失效是因为Get-ChildItem -Recurse会一次性遍历所有层级的文件和文件夹,把它们全部存入$items列表。即使某个父文件夹的权限继承已禁用,它的子项已经被提前获取到了,continue只能跳过当前的父文件夹项,无法阻止后续处理它的子项。
解决方案:递归遍历+提前终止
改用递归函数遍历目录,遇到权限继承禁用的文件夹时,直接停止遍历其下的所有子项,从根源上避免处理这些内容。
修正后的脚本
function Process-Item { param( [Parameter(Mandatory=$true)] [string]$Path ) $item = Get-Item $Path $acl = Get-Acl $Path # 检查当前项是否是继承禁用的文件夹 if ($item.PSIsContainer -and $acl.AreAccessRulesProtected) { Write-Host "Skipping folder and all subitems: $Path (inheritance disabled)" return # 终止递归,不处理子项 } # 添加权限规则 $accessRules = @( New-Object System.Security.AccessControl.FileSystemAccessRule("domain\group-FC", "FullControl", "Allow"), New-Object System.Security.AccessControl.FileSystemAccessRule("domain\group-Home-RO", "ReadAndExecute", "Allow"), New-Object System.Security.AccessControl.FileSystemAccessRule("domain\group-Home-RW", "Modify", "Allow") ) foreach ($rule in $accessRules) { $acl.AddAccessRule($rule) } Set-Acl $Path $acl Write-Host "Added permissions to: $Path" # 如果是文件夹,递归处理子项 if ($item.PSIsContainer) { Get-ChildItem $Path | ForEach-Object { Process-Item -Path $_.FullName } } } # 启动处理,替换为你的目标路径 Process-Item -Path "\\server\file\share"
关键改进点
- 递归遍历控制:遇到继承禁用的文件夹时,用
return终止递归,直接跳过其下所有子项,而不是先获取所有项再逐个跳过。 - 代码简洁性:将权限规则存入数组,用循环添加,减少重复代码。
- 精准判断:先判断当前项是否是文件夹,再检查继承状态,避免对文件做无效判断(文件的继承状态由父文件夹决定,这里仅处理父文件夹未禁用继承的文件)。
额外注意事项
- 运行脚本需要管理员权限,否则可能无法修改权限。
- 建议先在测试环境验证,避免误改生产环境权限。
- 如果需要跳过已添加过权限的项,可以在添加前检查ACL中是否已存在对应规则,避免重复操作。
内容的提问来源于stack exchange,提问作者Clint Rocks
相关产品推荐
相关产品推荐

