ドライブ容量は簡単ですね。 cim でも wmi でもいいでしょう。
さて、ドライブの次はフォルダ容量を調べてみましょう。
特に多くの場合は、 容量を調べる = どのファイル/フォルダが原因かを調べるため
なので大事です。
では、見てみましょう。
目次
フォルダの容量 = ファイルの容量合計
正確には違います。 さらに正確にいうと ACE/ACL (所有者設定/セキュリティ権限) や 隠しファイル などにより、取得には制限がかかる場合があるためです。
ただ、一般的にこれらのファイルは通常のファイルを調べたうえで更に問題と思わしきときに調べるのが筋でしょう。
よって、今回は実行ユーザーで見えるフォルダ内部のファイル容量を合計することにしましょう。*1
コードサンプル
例として、 c:\logs のフォルダ容量を見てみたいとするとこのような感じで書けます。
ワンライナー (定番)
# Oneliner Get-ChildItem c:\logs -Recurse | where PSIsContainer | %{$i=$_;$subFolderItems = (Get-ChildItem $i.FullName | where Length | measure Length -sum);[PSCustomObject]@{Fullname=$i.FullName;MB=[decimal]("{0:N2}" -f ($subFolderItems.sum / 1MB))}} | sort MB -Descending | ft -AutoSize
このような感じで容量順に表示されます。
Fullname MB -------- -- C:\logs\past 1000.00 C:\logs\source0 10.00 C:\logs\sources 6.00 C:\logs\test 2.00
ワンライナー (改行付で)
少し見やすくしましょう。
# refine oneliner Get-ChildItem c:\logs -Recurse ` | where PSIsContainer ` | %{ $i=$_ $subFolderItems = (Get-ChildItem $i.FullName | where Length | measure Length -sum) [PSCustomObject]@{ Fullname=$i.FullName MB=[decimal]("{0:N2}" -f ($subFolderItems.sum / 1MB)) }} ` | sort MB -Descending ` | format-Table -AutoSize
分離
ある程度以上の容量でないと、逆に実行速度遅くなります。
$folder = Get-ChildItem c:\logs -recurse | where PSIsContainer [array]$volume = foreach ($i in $folder) { $subFolderItems = (Get-ChildItem $i.FullName | where Length | measure Length -sum) [PSCustomObject]@{ Fullname=$i.FullName MB=[decimal]("{0:N2}" -f ($subFolderItems.sum / 1MB)) } } $volume | sort MB -Descending | ft -AutoSize
function化
使いやすくしましょう。
function Get-DirectoryVolume{ [CmdletBinding()] param( [parameter( position = 0, mandatory, valuefrompipelinebypropertyname, valuefrompipeline)] [string] $path = $null, [parameter( position = 1, mandatory = 0, valuefrompipelinebypropertyname, valuefrompipeline)] [string] $scale = "MB" ) Get-ChildItem $path -Recurse ` | where PSIsContainer ` | %{ $i = $_ $subFolderItems = (Get-ChildItem $i.FullName | where Length | measure Length -sum) [PSCustomObject]@{ Fullname = $i.FullName MB = [decimal]("{0:N2}" -f ($subFolderItems.sum / "1$Scale")) }} ` | sort $scale -Descending ` | Format-Table -AutoSize }
実行時にパスを指定できます。
Get-DirectoryVolume -path C:\Logs
イベント通知でもいいですし、フォルダ容量管理が遠隔できればあとは簡単ですね。
修正
意外とみなさんに需要があるようなので、修正しておきます。
function Get-DirectoryVolume { [CmdletBinding()] param ( [parameter( position = 0, mandatory = 1, valuefrompipeline = 1, valuefrompipelinebypropertyname = 1)] [string[]] $Path = $null, [parameter( position = 1, mandatory = 0, valuefrompipelinebypropertyname = 1)] [validateSet("KB", "MB", "GB")] [string] $Scale = "KB", [parameter( position = 2, mandatory = 0, valuefrompipelinebypropertyname = 1)] [switch] $Recurse = $false, [parameter( position = 3, mandatory = 0, valuefrompipelinebypropertyname = 1)] [switch] $Ascending = $false, [parameter( position = 4, mandatory = 0, valuefrompipelinebypropertyname = 1)] [switch] $OmitZero ) process { $path ` | %{ Write-Verbose ("Checking path : {0}. Scale : {1}. Recurse switch : {2}. Decending : {3}" -f $_, $Scale, $Recurse, !$Ascending) if (Test-Path $_) { $result = Get-ChildItem -Path $_ -Recurse:$Recurse ` | where PSIsContainer ` | %{ $subFolderItems = (Get-ChildItem $_.FullName | where Length | measure Length -sum) [PSCustomObject]@{ Fullname = $_.FullName $scale = [decimal]("{0:N4}" -f ($subFolderItems.sum / "1{0}" -f $scale)) }} ` | sort $scale -Descending:(!$Ascending) if ($OmitZero) { return $result | where $Scale -ne ([decimal]("{0:N4}" -f "0.0000")) } else { return $result } } } } }
これで、以下が可能になりました。
- Pipeline入力を受け付け
- 複数のパス対応
- Scaleの選択
- Recurseの選択
- 0出力の省略
Get-DirectoryVolume -path D:\GitHub, c:\logs -scale KB Get-DirectoryVolume -path D:\GitHub, c:\logs -scale KB Get-DirectoryVolume -path D:\GitHub, c:\logs -scale KB -Ascending Get-DirectoryVolume -path D:\GitHub, c:\logs -scale KB -Ascending -OmitZero "c:\logs", "D:\GitHub" | Get-DirectoryVolume -scale KB "c:\logs", "D:\GitHub" | Get-DirectoryVolume -scale MB -Recurse -Verbose
GitHub
コードを公開しておきます。
GitHub - PowerShellUtil / Get-DirecotryVolume
*1:このことから、Administrator で実行すると Windows/Program Files でも動作するのでいいかもしれません。