我正在尝试编写一个powershell脚本,它将递归地遍历一个目录,并报告任何具有“非”继承权限的文件或目录。
我觉得我离这个很近了
Get-ChildItem -path 'C:\xyzzy' -Recurse | ForEach-Object {
$fullpath = $_.FullName
(get-acl -path $_.FullName).Access | ForEach-Object {
if ($_.IsInherited -ne 'True') {
write-output $fullpath
}
}
}
这看起来很有效,但是在一个大的目录树上运行起来非常慢。有人有什么建议可以加快这个速度吗?
谢谢!
2条答案
按热度按时间qc6wkl3g1#
下面的代码应该比您当前所做的要快得多,它使用
Queue<T>
而不是Get-ChildItem
来遍历目录,并且由于您使用的是PowerShell 5.1,因此可以使用FileInfo
和DirectoryInfo
的GetAccessControl()
示例方法来代替Get-Acl
。最后在这里:
由于您只对在存在任何非继承规则的情况下获取文件或文件夹的绝对路径感兴趣,因此只要满足条件,就应停止上述循环,无需枚举所有规则。
注意,此代码包括隐藏文件和文件夹。
toiithl62#
要提供Santiago Squarzon's helpful answer的替代方案:
它可能不那么快,但在实践中可能足够快,并且具有概念上更简单和更简洁的优点:
Get-Acl
* 一次,而是使用一个直接从管道获取输入的 * 单个 * 调用,这将大大加快操作速度。$_.Access.IsInherited
使用member-access enumeration返回由.Access
返回的所有规则中的所有.Inherited
属性值,并且-contains $false
测试是否至少有一个值为$false
。-PipelineVariable
参数来存储当前文件系统项,作为Get-ChildItem
在自选变量$item
中的输出,使其可用于后面管道段中的脚本块。-PipeLineVariable
,但它构成了完整路径(.FullName
属性),而Get-Acl
输出对象本身具有(ETS).Path
属性,其值以PowerShell provider前缀开头,即Microsoft.PowerShell.Core\FileSystem::
,必须将其删除(您可以使用$_.Path -replace '^[^:]+::'
执行此操作)如果您不关心 * 流式 * 输出-特别是查看 * 正在生成的 * 输出-您可以进一步加快上述操作,如下所示: