Мне стало любопытно об этой проблеме и начал работать над чем-то.Есть ряд проблем, но я хотел опубликовать «общую идею».
Начните с получения FullNames и добавления информации ACL к имени файла:
$x = (Get-ChildItem C:\Users\j309921\Desktop\ -Recurse).FullName | ForEach-Object {
"$_ - $((Get-Acl -Path $_).Access.AccessControlType | Select-Object -Unique)"
}
Почему-то яобнаружил, что GCI не всегда возвращает все пути.Я еще не изучал это поведение.Во всяком случае ...
Затем я сделал эту функцию, чтобы отделить пути и поместить их в объекты.Я думаю, что это можно заменить на скорость, но это облегчает работу в следующих частях.
function Convert-GCItoObject {
param(
[Parameter(Mandatory, ValueFromPipeline, HelpMessage='Items to process')]$InputObject
)
process {
$output = @()
$InputObject -split '\\' | ForEach-Object{ $output += $_ }
for($i=$output.Count-1; $i -gt 0; $i--){
$output[$i-1] = [pscustomobject]@{$output[$i-1] = $output[$i]}
}
$output[0]
}
}
$x = $x | Convert-GCItoObject
Затем я сделал свою первую рекурсивную функцию, которая строит дерево объектов на основе путей, возвращаемыхпоследняя функция.Если есть каталог, он перезапускает функцию.Таким образом, вы получаете прогресс в создании объектов снизу вверх.
function Recurse-GCIObject {
param(
[Parameter(Mandatory, HelpMessage='Items to process')]$object
)
$pscustomobject = [pscustomobject]@{}
$object | Where-Object {$_} | Where-Object {$_.GetType().Name -ne 'String'} | ForEach-Object {$_.psobject.properties.name} | Select-Object -Unique | ForEach-Object {
if($object.$_) {
$pscustomobject | Add-Member @{$_ = $(Recurse-GCIObject -object $object.$_) }
}
}
try {
$pscustomobject | Add-Member -Name Contains -Value ($object | Where-Object {$_.GetType().Name -eq 'String' -and -not $pscustomobject.$_}) -MemberType NoteProperty -ErrorAction Stop
} catch {
Write-Verbose 'Empty'
}
$pscustomobject
}
$x = Recurse-GCIObject -object $x
На данный момент объект довольно пригоден для использования.Я сделал быструю функцию, чтобы сделать красивое дерево.Я не тратил много времени на это, но это читабельно.
function Out-Tree {
param(
[Parameter(Mandatory, ValueFromPipeline, HelpMessage='Items to process')]$InputObject, $lvl = 0
)
process {
if($lvl -gt 0) { $tab = (0..$lvl | ForEach-Object {"`t"}) } else {$tab = ''}
$InputObject | Where-Object {$_} | ForEach-Object {$_.psobject.properties.name} | ForEach-Object {
if ($_ -ne 'Contains') {
"$tab+-- $_ `n"
if($InputObject.$_) {
"$($InputObject.$_ | Out-Tree -lvl ($lvl + 1) )"
}
}
}
$InputObject.Contains | Where-Object {-not [string]::IsNullOrEmpty($_)} | ForEach-Object { "$tab|`t|-- $_ `n" }
}
}
$x | Out-Tree
Есть ряд проблем с этим.Это очень медленно, вывод GCI иногда не отображает всю правильную информацию, а также дерево может быть намного лучше.Но я хотел опубликовать это как больше POC / упражнение.Я мог бы улучшить его позже и пригласить кого-нибудь еще.