Дерево папок с разрешениями NTFS - PullRequest
0 голосов
/ 01 октября 2018

Я пытаюсь создать небольшой скрипт с помощью PowerShell, но я застрял.

Мне нужно выдать структуру папки в виде дерева с разрешениями NTFS.

C:\TEST
├───Test1 - Access
│   ├───Test1.1 - Access
│   └───Test1.2 - Access
│       └───Test1.2.1 - Access
├───Test2 - Access
│   ├───Test2.1 - Access
│   └───Test2.2 - Access
├───Test3 - Access
└───Test4 - Access
    ├───Test4.1 - Access
    ├───Test4.2 - Access
    └───Test4.3 - Access

Примерно так.

Я пробовал с Get-ChidlItem C:\Test -Recurse и Get-Acl, но не мог понять, как отобразить результаты в виде дерева.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Мне стало любопытно об этой проблеме и начал работать над чем-то.Есть ряд проблем, но я хотел опубликовать «общую идею».

Начните с получения 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 / упражнение.Я мог бы улучшить его позже и пригласить кого-нибудь еще.

0 голосов
/ 01 октября 2018

Ниже приведен скрипт, который я недавно написал для вывода структуры каталогов в виде дерева с размерами файлов на консоль.

Вы можете легко изменить строки Write-Host, чтобы удалить размеры файлов и добавить их в свой файл.Информация ACL (я не очень эстетически уверен, как это будет работать).

Большим ограничением использования Write-Host является то, что вы не можете работать с данными дальше по сценарию, вы не можете выводить данные в файл - Start-Transcript теряет форматирование.

Комментарии Джейкоба Колвина описывают гораздо лучший подход, который мне было бы интересно увидеть на практике.

Единственный другой подход, о котором я мог подумать, - это создание объекта, объединяющего Get-ACL иGet-ChildItem данных, а затем при выводе данных, считая \ в структуре каталогов для создания отступа.

function Show-Tree
{
    param
    (
        $directory
    )
    if ((Get-PSCallStack)[1].Command -eq 'Show-Tree') {
        Write-host "├──" -NoNewline
        if(Test-Path $directory/*)
        {
            Write-host "┬" -NoNewline
        }
        else
        {
            Write-host "─" -NoNewline
        }
        Write-Host "$($directory | Split-Path -Leaf)/"
    }
    else
    {
        Write-Host "$directory"
        $Script:StartingIndent = ($directory).Split("\").Count+1
    }
    Get-ChildItem -path $directory -File | % { 
        $i = 0
        $indent = ($_.FullName).Split("\").Count-$script:StartingIndent
        while($i -lt $indent)
        {
            [console]::Write("│  ")
            $i++
        }
        if(($_.length / 1MB) -ge 1)
        {
            Write-Host "├───[$([int]($_.length / 1MB)) MB] $($_.name)"
        }
        elseif(($_.length / 1KB -ge 1))
        {
            Write-Host "├───[$([int]($_.length / 1KB)) KB] $($_.name)"
        }
        else
        {
            Write-Host "├───[$($_.length) B] $($_.name)"
        }
    }
    Get-ChildItem -Path $directory -Directory | % {
        $i = 0
        $indent = ($_.FullName).Split("\").Count-$script:StartingIndent
        while($i -lt $indent)
        {
            Write-host "│  " -NoNewline
            $i++
        }
        Show-Tree -directory $_.FullName
    }
}

Show-Tree -directory C:\Testing

Вывод

C:\Testing
├───[7 KB] $RY3NETI.prop
├───[9 KB] Book1.xlsx
├───[308 B] csvOut.csv
├───[308 B] csvOut2.csv
├───[297 B] csvout3.csv
├───[6 MB] Shakespear.txt
├───[570 KB] ShakeSpeareUniqueWords.txt
├───[1 KB] Transcript.txt
├──┬Test1/
│  ├───[183 B] filename.rtf
│  ├───[7 KB] img3.png
│  ├───[18 KB] img4.png
│  ├───[43 KB] img5.png
│  ├───[19 KB] img7.png
│  ├───[26 KB] test.doc
├──┬Test2/
│  ├───[83 MB] filetest.rar
│  ├───[7 KB] img10.png
│  ├───[18 KB] img9.png
│  ├──┬Test2 Subfolder/
│  │  ├───[33 KB] img1.png
│  │  ├───[17 KB] img2.png
│  │  ├───[14 KB] img8.png
...