Список каталогов с именем и размером - PullRequest
2 голосов
/ 30 января 2020

Я хотел бы перечислить каталоги с полным именем, размером, LastWriteTime и повторять до третьего уровня.

Get-ChildItem -Depth 3 |
    Where-Object {
        $_.PSIsContainer
        } |
    ForEach-Object {
        $_.FullName + ";" + "{0:N2}" -f ((Get-ChildItem $_ -Recurse |
            Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB) + " MB"+";"+ $_.LastWriteTime
        }

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

Вывод:

C:\folder1\folder2 ; 487,69 MB ; 30.01.2020 17:58:45
C:\folder1\folder2\folder3 ; 0,00 MB ; 30.01.2020 17:59:34
C:\folder1\folder2\folder3\folder4 ; 0,00 MB ; 30.01.2020 17:59:37

Но так и должно быть, так как Я помещаю один и тот же файл в каждую папку:

C:\folder1\folder2 ; 1463,07 MB ; 30.01.2020 17:58:45
C:\folder1\folder2\folder3 ; 975,38 MB ; 30.01.2020 17:59:34
C:\folder1\folder2\folder3\folder4 ; 487,69 MB ; 30.01.2020 17:59:37

Ответы [ 2 ]

1 голос
/ 30 января 2020

Это выводит FullName, Size и LastWriteTime каталога. Обратите внимание, что size пусто, тогда ничего не выводится:

Get-ChildItem -Depth 3 | 
    Where-Object { $_.PSIsContainer} |
    foreach{
        $size = "{0:N2}" -f ((Get-ChildItem $_ -Recurse | 
            Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB)

        if ($size){
            Write-Host $_.FullName  ";"  $size "MB" ";" $_.LastWriteTime
        }
    }

Сообщите нам, как вы попали.

Обновление

После обновления вашего вопроса Пожалуйста, попробуйте следующий код:

Get-ChildItem -Depth 3 | 
    Where-Object { $_.PSIsContainer} |
    foreach{
        $folders = Get-ChildItem $_.FullName -Recurse

        [int]$totalSize = 0

        foreach ($folder in $folders){
            $totalSize += (Get-ItemProperty -Path $folder.FullName -Name Length -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Length)
        }

        if ($totalSize){
            Write-Host $_.FullName  ";"  $totalSize ";" $_.LastWriteTime
        }
    }

Возможно, его можно очистить, я просто хочу посмотреть, работает ли он так, как вы хотите:)

0 голосов
/ 30 января 2020

Что вам нужно сделать, это проверить содержимое каждого подкаталога и добавить его к общему количеству родительского каталога. Затем этот родитель должен сказать, что это супер-родитель, а этот дедушка => прадедушка и т. Д. 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. .

...