A PowerShell解决方案建立在蒙托内罗的有用答案 https://stackoverflow.com/a/54289749/45375并改进了以下几个方面:
- 控制递归深度
- 提高性能
- 与其他 cmdlet 更好地集成以实现可组合功能
基于函数的示例调用Get-DirectorySize
定义如下:
# Get the size of the current directory (only).
Get-DirectorySize
# As requested by the OP:
# Recursively report the sizes of all subdirectories in the current directory.
Get-DirectorySize -Recurse -ExcludeSelf
# Get the size of all child directories and sort them by size, from largest
# to smallest, showing only the 5 largest ones:
Get-DirectorySize -Depth 1 -ExcludeSelf |
Sort-Object Size -Descending |
Select-Object -First 5
最后一个命令的输出示例:
FullName FriendlySize Size
-------- ------------ ----
C:\Users\jdoe\AppData 3.27gb 3514782772
C:\Users\jdoe\Desktop 801.40mb 840326199
C:\Users\jdoe\.nuget 778.97mb 816814396
C:\Users\jdoe\.vscode 449.12mb 470931418
C:\Users\jdoe\Projects 104.07mb 109127742
请注意属性.FriendlySize
包含一个友好的、自动缩放的string大小的表示,而.Size
是一个数字([long]
)包含实际字节数,这有助于进一步的编程处理。
注意:向输出对象添加属性以方便友好的显示这里只是为了实现方便才这样做。正确的 Powershell 方法是根据输出对象类型定义格式化指令 - 请参阅the docs https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_format.ps1xml.
Caveats(也适用于链接的答案):
Get-DirectorySize
源代码
注意:需要 Windows PowerShell v3+;还兼容 PowerShellCore.
function Get-DirectorySize
{
param(
[Parameter(ValueFromPipeline)] [Alias('PSPath')]
[string] $LiteralPath = '.',
[switch] $Recurse,
[switch] $ExcludeSelf,
[int] $Depth = -1,
[int] $__ThisDepth = 0 # internal use only
)
process {
# Resolve to a full filesystem path, if necessary
$fullName = if ($__ThisDepth) { $LiteralPath } else { Convert-Path -ErrorAction Stop -LiteralPath $LiteralPath }
if ($ExcludeSelf) { # Exclude the input dir. itself; implies -Recurse
$Recurse = $True
$ExcludeSelf = $False
} else { # Process this dir.
# Calculate this dir's total logical size.
# Note: [System.IO.DirectoryInfo].EnumerateFiles() would be faster,
# but cannot handle inaccessible directories.
$size = [Linq.Enumerable]::Sum(
[long[]] (Get-ChildItem -Force -Recurse -File -LiteralPath $fullName).ForEach('Length')
)
# Create a friendly representation of the size.
$decimalPlaces = 2
$padWidth = 8
$scaledSize = switch ([double] $size) {
{$_ -ge 1tb } { $_ / 1tb; $suffix='tb'; break }
{$_ -ge 1gb } { $_ / 1gb; $suffix='gb'; break }
{$_ -ge 1mb } { $_ / 1mb; $suffix='mb'; break }
{$_ -ge 1kb } { $_ / 1kb; $suffix='kb'; break }
default { $_; $suffix='b'; $decimalPlaces = 0; break }
}
# Construct and output an object representing the dir. at hand.
[pscustomobject] @{
FullName = $fullName
FriendlySize = ("{0:N${decimalPlaces}}${suffix}" -f $scaledSize).PadLeft($padWidth, ' ')
Size = $size
}
}
# Recurse, if requested.
if ($Recurse -or $Depth -ge 1) {
if ($Depth -lt 0 -or (++$__ThisDepth) -le $Depth) {
# Note: This top-down recursion is inefficient, because any given directory's
# subtree is processed in full.
Get-ChildItem -Force -Directory -LiteralPath $fullName |
ForEach-Object { Get-DirectorySize -LiteralPath $_.FullName -Recurse -Depth $Depth -__ThisDepth $__ThisDepth }
}
}
}
}
这是基于评论的帮助对于功能;如果您将该功能添加到您的$PROFILE
,将帮助直接放在函数上方或函数体内,以获得对-?
并自动集成Get-Help
.
<#
.SYNOPSIS
Gets the logical size of directories in bytes.
.DESCRIPTION
Given a literal directory path, output that directory's logical size, i.e.,
the sum of all files contained in the directory, including hidden ones.
NOTE:
* The logical size is distinct from the size on disk, given that files
are stored in fixed-size blocks. Furthermore, files can be compressed
or sparse.
Thus, the size of regular files on disk is typically greater than
their logical size; conversely, compressed and sparse files require less
disk space.
Finally, the list of child items maintained by the filesystem for each
directory requires disk space too.
* Wildcard expressions aren't directly supported, but you may pipe in
Output from Get-ChildItem / Get-Item; if files rather than directotries
happen to be among the input objects, their size is reported as-is.
CAVEATS:
* Can take a long time to run with large directory trees, especially with
-Recurse.
* Recursion is implemented inefficently.
.PARAMETER LiteralPath
The literal path of a directory. May be provided via the pipeline.
.PARAMETER Recurse
Calculates the logical size not only of the input directory itself, but of
all subdirectories in its subtree too.
To limit the recursion depth, use -Depth.
.PARAMETER Depth
Limits the recursion depth to the specified number of levels. Implies -Recurse.
Note that 0 means no recursion. Use just -Recurse in order not to limit the
recursion.
.PARAMETER ExcludeSelf
Excludes the target directory itself from the size calculation.
Implies -Recurse. Since -Depth implies -Recurse, you could use -ExcludeSelf
-Depth 1 to report only the sizes of the immediate subdirectories.
.OUTPUTS
[pscustomobject] instances with properties FullName, Size, and FriendlySize.
.EXAMPLE
Get-DirectorySize
Gets the logical size of the current directory.
.EXAMPLE
Get-DirectorySize -Recurse
Gets the logical size of the current directory and all its subdirectories.
.EXAMPLE
Get-DirectorySize /path/to -ExcludeSelf -Depth 1 | Sort-Object Size
Gets the logical size of all child directories in /path/to without including
/path/to itself, and sorts the result by size (largest last).
#>