一个建立在 montonero有用的答案 基础上的 PowerShell 解决方案,改进了以下方面:
- 递归深度的控制
- 性能的提升
- 更好的与其他 cmdlet 集成以实现可组合功能
下面是基于定义如下的函数 Get-DirectorySize
的示例调用:
Get-DirectorySize
Get-DirectorySize -Recurse -ExcludeSelf
Get-DirectorySize -Depth 1 -ExcludeSelf |
Sort-Object Size -Descending |
Select-Object -First 5
last命令的示例输出:
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
包含友好的自动缩放大小的
字符串表示,而
.Size
是一个数字(
[long]
),其中包含实际的字节计数,这是有助于进一步的程序处理。
注:在此仅为实现方便,将属性添加到输出对象中仅用于促进
友好的显示。正确的Powershell方式是根据输出对象类型定义格式化指令 - 请参见
文档。
警告(也适用于链接的答案):
Get-DirectorySize
源代码
注:需要Windows PowerShell v3+;也与PowerShell
Core兼容。
function Get-DirectorySize
{
param(
[Parameter(ValueFromPipeline)] [Alias('PSPath')]
[string] $LiteralPath = '.',
[switch] $Recurse,
[switch] $ExcludeSelf,
[int] $Depth = -1,
[int] $__ThisDepth = 0
)
process {
$fullName = if ($__ThisDepth) { $LiteralPath } else { Convert-Path -ErrorAction Stop -LiteralPath $LiteralPath }
if ($ExcludeSelf) {
$Recurse = $True
$ExcludeSelf = $False
} else {
$size = [Linq.Enumerable]::Sum(
[long[]] (Get-ChildItem -Force -Recurse -File -LiteralPath $fullName).ForEach('Length')
)
$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 }
}
[pscustomobject] @{
FullName = $fullName
FriendlySize = ("{0:N${decimalPlaces}}${suffix}" -f $scaledSize).PadLeft($padWidth, ' ')
Size = $size
}
}
if ($Recurse -or $Depth -ge 1) {
if ($Depth -lt 0 -or (++$__ThisDepth) -le $Depth) {
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).
#>
Get-ChildItem $startFolder
中也添加-Force
(以包括隐藏目录)。PSv3引入了-Directory
和-File
开关到Get-ChildItem
,这使得Where-Object {$_.PSIsContainer -eq $true}
和Where-Object {$_.PSIsContainer -eq $false}
不再必要。虽然它没有被文档化,但是Get-ChildItem
在输出之前总是按名称排序,因此Sort-Object
调用是不必要的。 - mklement0