ファイルの所有者を一覧したいという要件がありました。もともと dir /q /s でスキャンしていましたが、手順書の中で繰り返し実行しており、トータルではかなり時間がかかっていました。
繰り返しスキャンが必要になっている原因としては dir /q /s の結果は再利用性が乏しいからです。
それなら、ということで Get-ChildItem -r | Get-Acl を使ってみると非常に遅いです。どうやら毎回 AD サーバに所有者情報を問い合わせしているらしく、コマンドが終わりませんでした。
そこで AD サーバに問い合わせた結果をメモリ上にキャッシュするようにしました。
Get-ChildItem -Recurse `
| ForEach-Object -begin {
$cache = @{}
} -Process {
# アクセス制御オブジェクトの取得
if ($_.PSIsContainer) {
$AccessControl = [System.IO.Directory]::GetAccessControl($_.FullName)
} else {
$AccessControl = [System.IO.File]::GetAccessControl($_.FullName)
}
# 所有者のSIDオブジェクトを取得
$Sid = $AccessControl.GetOwner([System.Security.Principal.SecurityIdentifier])
# キャッシュにヒットしない場合
if (-not $cache.containsKey($Sid.Value)) {
try {
# SIDの名前解決のために Active Directory に問い合わせ
$NTAccount = $Sid.Translate([System.Security.Principal.NTAccount])
# キャッシュに保存
$cache.add($Sid.Value, $NTAccount.Value)
} catch {
# SIDの名前解決に失敗した場合は SID を保存
$cache.add($Sid.Value, $Sid.Value)
}
}
# オブジェクトを返す
[pscustomobject]@{
Owner = $cache[$sid.Value]
Path = $_.FullName
}
}
これで、だいたい速いのではないでしょうか。もっと早くしたいときは並列実行すれば良いと思いますが、ファイルのスキャンが先に詰まると思います。