Что вам нужно сделать, это проверить содержимое каждого подкаталога и добавить его к общему количеству родительского каталога. Затем этот родитель должен сказать, что это супер-родитель, а этот дедушка => прадедушка и т. Д. c.
Каждый файл должен информировать каждого предка о своем размере, иначе каталоги, вложенные в 30 глубин с гигабайтами данных, не смогут, например, сообщить диску C: насколько он большой.
Это проблема рекурсии, и вы можете либо сделать это, вызвав функцию для каждого дочернего элемента, либо создать очередь и обработать каждого дочернего элемента по мере ее поступления.
Вы также можете вычислить каждый каталог, а затем каталоги свернуть свои результаты, или вы можете иметь каждый файл отчета. В зависимости от того, есть ли у вас широкая или глубокая файловая структура, это может иметь значение, но, возможно, незначительно.
Я записал это в виде очереди с каждым отчетным файлом. На мой взгляд, немного легче следовать, если вы пробьете код, чем с помощью стека вызовов и окончательного накопления.
function Get-DirSize {
[CmdletBinding()]
param (
[Parameter(Position = 0,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "Directory path")]
[ValidateNotNullOrEmpty()]
$name = (Get-Item ".")
, [switch]$force
)
$name = Get-Item $name
$q = New-Object System.Collections.Queue
$results = New-Object System.Collections.Queue
$q.Enqueue([PSCustomObject]@{
Parent = $null
Directory = $name
Size = 0
Depth = 0
})
do {
$dir = $q.Dequeue()
$results.Enqueue($dir)
$children = $dir.Directory | Get-ChildItem -Force:$force
foreach ($child in $children) {
if ($child.PSIsContainer ) {
$q.Enqueue([PSCustomObject]@{
Parent = $dir
Directory = $child
Size = 0
Depth = $dir.Depth + 1
})
}
else {
$tempDir = $dir
while ($tempDir) {
$tempDir.Size += $child.length
$tempDir = $tempDir.Parent
}
}
}
} until ($q.Count -eq 0)
$ret = $results | ForEach-Object {
$dir = $_
return [PSCustomObject]@{
FullName = $dir.Directory.FullName
LastWriteTime = $dir.Directory.LastWriteTime
Size = $dir.Size
Depth = $dir.Depth
PSDirObject = $dir.Directory
}
}
return $ret
}
Затем вы вызываете его и можете передать каталог, который хотите проверить или текущий рабочий каталог. Флаг -force просто передается get-childitem и будет иметь тот же эффект.
Get-DirSize "c:\development" -force | Where-Object Depth -LE 3 | Select-Object FullName, LastWriteTime, @{n = "Size"; e = { "$($_.Size / 1MB)" + "MB" } }
Выходные данные должны быть отфильтрованы по глубине, и вы можете выбрать столбцы, которые вы хотите, с помощью специального оператора select. .