【问题标题】:How to recurse through folders and determine the folder size?如何递归遍历文件夹并确定文件夹大小?
【发布时间】:2025-12-03 03:30:01
【问题描述】:

我在“Windows PowerShell Tip of the Week”中有一个稍微修改过的脚本版本。这个想法是确定文件夹及其子文件夹的大小:

$startFolder = "C:\Temp\"

$colItems = (Get-ChildItem $startFolder | Measure-Object | Select-Object -ExpandProperty count)
"$startFolder -- " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"

$colItems = (Get-ChildItem $startFolder -recurse | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems)
    {
        $subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum)
        $i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
    }

此脚本运行良好,但对于某些文件夹,我收到一条错误消息:

Measure-Object : Property "length" cannot be found in any object(s) input.
At line:10 char:70
+         $subFolderItems = (Get-ChildItem $i.FullName | Measure-Object <<<<  -property length -sum)
    + CategoryInfo          : InvalidArgument: (:) [Measure-Object], PSArgumentException
    + FullyQualifiedErrorId : GenericMeasurePropertyNotFound,Microsoft.PowerShell.Commands.MeasureObjectCommand

这个错误的原因是什么以及如何改进脚本来克服?

【问题讨论】:

    标签: windows powershell directory powershell-2.0


    【解决方案1】:

    我在 Windows 7 上运行它,它可以工作(剪切和粘贴您的代码)。也许您的路径中有一个“名字不好”的文件?

    【讨论】:

    • 如果特定目录中只有目录会发生这种情况,因为DirectoryInfo 没有Length 属性。
    • +1 @Joey - 是的,我从 Measure-Object 得到了同样的错误,而你的错误是唯一解释它的解释。谢谢。
    【解决方案2】:

    Measure-Object 可以使用-ErrorAction 参数:

    $subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum -ErrorAction SilentlyContinue)
    

    或其别名-ea带有一个数值,非常适合在交互式实验中快速添加它:

    $subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum -ea 0)
    

    在我看来,Technet 上的脚本是非常糟糕的 PowerShell 代码。

    作为一种非常快速和肮脏(且缓慢)的解决方案,您还可以使用以下单线:

    # Find folders
    Get-ChildItem -Recurse | Where-Object { $_.PSIsContainer } |
    # Find cumulative size of the directories and put it into nice objects
    ForEach-Object {
        New-Object PSObject -Property @{
            Path = $_.FullName
            Size = [Math]::Round((Get-ChildItem -Recurse $_.FullName | Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB, 2)
        }
    } |
    # Exclude empty directories
    Where-Object { $_.Size -gt 0 } |
    # Format nicely
    Format-Table -AutoSize
    

    或者实际上是单线:

    gci -r|?{$_.PSIsContainer}|%{New-Object PSObject -p @{Path=$_.FullName;Size=[Math]::Round((gci -r $_.FullName|measure Length -s -ea 0).Sum/1MB,2)}}|?{$_.Size}|ft -a
    

    【讨论】:

    • 谢谢,您的解决方案要好得多!
    • 您可以通过缓存更深的目录并在进一步计算层次结构时重新使用它们的大小来使其变得更好。 IE。记忆以避免一遍又一遍地重新计算更深的目录大小。