PowerShellを使ってサイズの大きいフォルダを検出する

コンピューターの中でどのフォルダが容量を多く占有しているのかを探索するのに便利なスクリプトを紹介

普段使用しているコンピューターには様々なアプリケーションがインストールされ、アップデートなどによって大量の一時ファイルなどが残ってしまう場合があります。いつの間にかハードディスクの空き容量がなくなってしまい、不要なファイルやフォルダを削除する必要が出てきます。

コンピューターの中でどのフォルダが容量を多く占有しているのかを探索するのに便利なスクリプトを紹介します。

Get-ChildItemコマンドを利用して、指定したフォルダを調査

Sample1.ps1
→ Sample1.ps1 ファイルダウンロード

Sample2.ps1
→ Sample2.ps1 ファイルダウンロード

この2つのスクリプトは、Get-ChildItemコマンドを利用して、指定したフォルダと配下のすべてのサブフォルダを探索して、容量の大きい上位20件を表示します。

Sample1.ps1は、フォルダ内のファイルの合計サイズを集計してフォルダサイズとしています。含まれるサブフォルダの容量は含まれておらず、純粋なフォルダ内のファイルの合計サイズとなります。

Sample2.ps2はフォルダ内のすべてのファイルとサブフォルダの合計サイズを集計しています。スクリプト内ではPowerShellの特徴である「パイプライン」を利用して、効率的にスクリプトを作成しています。Sample1.ps1とSample2.ps1のコードの違いは5行目と14行目の2箇所だけです。Sample1.ps1を元にコードを見ていきましょう。

Get-ChildItemコマンドを利用したフォルダサイズの取得方法

まずはルートフォルダ直下のファイルサイズを合計してフォルダサイズを取得します。パラメーターとして、探索対象のフォルダパスをルートフォルダとして指定します。パイプランを分解して一つずつ見ていきましょう。

$Items = (Get-ChildItem -Path $RootFolder -ErrorAction "SilentlyContinue" -Force | Where-Object {$_.GetType().Name -eq "FileInfo"} | Measure-Object -Property Length -Sum)

Get-ChildItem -Path $RootFolderでルートフォルダ内のオブジェクトを取得します。「-Force」オプションを付けることで、既定で非表示設定となっているフォルダやオプションも探索対象とすることができますが、フォルダやファイルによっては特殊なオブジェクトがあるためアクセスができなくエラーとなってしまうことがあります。

これらエラーは無視してコマンドを実行するために、-ErrorAction “SilentlyContinue”を指定しておきます。

Get-ChildItem -Path $RootFolder -ErrorAction "SilentlyContinue" -Force

Sample2.ps1では5行目に「-Recurse」オプションが付いています。

$Items = (Get-ChildItem -Path $RootFolder -ErrorAction "SilentlyContinue" -Force -Recurse
| Where-Object {$_.GetType().Name -eq "FileInfo"} | Measure-Object -Property Length -Sum)

このオプションは、ルートフォルダ配下のサブフォルダ内のファイルまで再帰的に取得するためのものです。Sample1.ps1とSample2.ps1の違いは、純粋なフォルダ内のファイルサイズの合計をフォルダのサイズとするか、フォルダ内のファイルとサブフォルダ、さらにサブフォルダ内のファイル、フォルダというように、すべてを含めてフォルダサイズとするかの違いとなります。

次にパイプラインで引き渡されたオブジェクトに対して、Where-Objectコマンドを使ってファイルのみ抽出しています。フォルダのサイズはフォルダ内に配置されたファイルのみの合計サイズとして計算する必要があります。ファイルのみを抽出するには、オブジェクトに対してGetType()コマンドを実行して、オブジェクト名が”FileInfo”となっている物を抽出します。$_ はパイプラインで引き渡されたオブジェクトが格納されています。これはPowerShellのあらかじめ決められている組み込み変数です。-eq はPowerShellの演算子で「=」(等号)の意味です。

Where-Object {$_.GetType().Name -eq "FileInfo"}

ファイルのみ抽出したオブジェクトに対して、Measure-Objectコマンドを使ってファイルサイズ(Lengthプロパティ)の合計値を-Sumオプションを付けて取得しています。最後に取得したオブジェクトを変数$Itemsに保存しておきます。

Measure-Object -Property Length -Sum

ルートフォルダのフォルダサイズ情報を配列に格納しておきます。この配列は最終的に、フォルダパスとフォルダサイズを配列に格納して、サイズ順に並び替え、上位10件を表示するため利用します。

[Array]$Folders = [PSCustomObject]@{
  "Fullname" = $RootFolder
  "Size(MB)" = ("{0:N1}" -F ($Items.Sum / 1MB))
}

$Folders変数が配列であることを定義します。

[Array]$Folders

[PSCustomObject]を使うと連想配列のフィールド名を独自に定義することができます(既定ではNameとValue)。フォルダパスと、フォルダサイズを格納します。フォルダサイズは見やすいように {0:N1} –FでMB単位でカンマ付の小数点第一位の値に表示形式を直して保存しています。

[PSCustomObject]@{
  "Fullname" = $RootFolder
  "Size(MB)" = ("{0:N1}" -F ($Items.Sum / 1MB))
  }

次にルートフォルダ配下のサブフォルダに対してサイズ取得を行います。Get-ChildItemコマンドで-Recurseオプションを指定すると、サブフォルダ内のサブフォルダ、さらにそのサブフォルダというようにすべての子オブジェクトを取得します。このブロックは、ルートフォルダとは異なりフォルダ一覧を取得するので、Where-Objectコマンドでは”DirectoryInfo”を指定してフォルダのみ抽出しています。

$Items = (Get-ChildItem -Path $RootFolder -ErrorAction "SilentlyContinue" -Recurse | Where-Object {$_.GetType().Name -eq "DirectoryInfo"})

取得したすべてのサブフォルダのオブジェクトそれぞれに対して、ファイルのサイズを合計してそれぞれのフォルダサイズとして計算していきます。すべてのフォルダ情報に対して処理を行う場合は、ForEach()の制御構文が便利です。$Itemsに格納されたオブジェクトを1つずつ順番に$iに格納してサイズ計算処理を行います。計算された全てのフォルダサイズ情報は、ルートフォルダの情報を格納した連想配列$Foldersに追加で格納します。

$Folders += ForEach ($i in $Items)
{

}

$iにはフォルダ情報がオブジェクトとして格納されています。それぞれルートフォルダと同様にファイルの合計サイズを計算して、フォルダサイズとして連想配列に格納します。

$SubFolderItems = (Get-ChildItem -Path $i.FullName -ErrorAction "SilentlyContinue" -Force | Where-Object {$_.GetType().Name -eq "FileInfo"} | Measure-Object -Property Length -Sum)

[PSCustomObject]@{
"Fullname" = $i.FullName
"Size(MB)" = [decimal]("{0:N1}" -F ($SubFolderItems.Sum / 1MB))
}

Sample2.ps1では14行目に「-Recurse」オプションが付いています。

$SubFolderItems = (Get-ChildItem -Path $i.FullName -ErrorAction "SilentlyContinue" -Force -Recurse
| Where-Object {$_.GetType().Name -eq "FileInfo"} | Measure-Object -Property Length -Sum)

ルートフォルダと同様に、サブフォルダ内のすべてのサブフォルダに対して再帰的にファイルを取得して合計しています。

Format-Tableコマンドでテーブル表示出力

最後にすべてのフォルダ情報を格納した連想配列$Foldersに対して、-Descendingオプションを使ってフォルダサイズを昇順で並べ替え、パイプラインを使って配列内の上位20件を抽出します。

さらにFormat-Tableコマンドを使って、テーブル表示で出力します。このとき-AutoSizeオプションを指定すると、自動でテーブルサイズなどを調整して出力します。

$Folders | Sort "Size(MB)" -Descending | Select-Object -First 20 | Format-Table -AutoSize

スクリプトの実行結果。(Sample1.ps1)

Get-VMProcessor TestVM | Select *Fullname
 
Size(MB)
--------
 
--------
C:\Program Files\Common Files\microsoft shared\ink
 
41.8
C:\Program Files\Windows Defender
 
10.2
C:\Program Files\Windows Journal
 
7.8
C:\Program Files\Hyper-V
 
6.8
C:\Program Files\Windows Photo Viewer
 
5.9
C:\Program Files\Hyper-V\6.3
 
5.5
C:\Program Files\Windows Mail
 
5.4
C:\Program Files\Hyper-V\6.2
 
4.9
C:\Program Files\Windows NT\Accessories
 
4.4
C:\Program Files\Common Files\System\Ole DB
 
3.4
C:\Program Files\Hyper-V\6.3\ja-JP
 
3.1
C:\Program Files\Hyper-V\ja-JP
 
2.9
C:\Program Files\Windows NT\TableTextService
 
2.8
C:\Program Files\Hyper-V\6.2\ja-JP
 
2.7
C:\Program Files\Windows Media Player
 
2.6
C:\Program Files\Common Files\System\ado
 
2.6
C:\Program Files\Internet Explorer
 
2.4
C:\Program Files\Common Files\System
 
1.8
C:\Program Files\Common Files\System\msadc
 
1.7
C:\Program Files\Common Files\microsoft shared\ink\en-US
 
1.0

スクリプトの実行結果。(Sample2.ps1)

Get-VMProcessor TestVM | Select *Fullname
 
Size(MB)
--------
 
--------
C:\Program Files\Common Files
 
55
C:\Program Files\Common Files\microsoft shared
 
45.4
C:\Program Files\Common Files\microsoft shared\ink
 
43.4
C:\Program Files\Hyper-V
 
25.9
C:\Program Files\Windows Defender
 
10.4
C:\Program Files\Common Files\System
 
9.7
C:\Program Files\Hyper-V\6.3
 
8.6
C:\Program Files\Windows Journal
 
8.4
C:\Program Files\Hyper-V\6.2
 
7.6
C:\Program Files\Windows NT
 
7.3
C:\Program Files\Windows Photo Viewer
 
5.9
C:\Program Files\Windows Mail
 
5.9
C:\Program Files\Windows NT\Accessories
 
4.5
C:\Program Files\Common Files\System\Ole DB
 
3.5
C:\Program Files\Hyper-V\6.3\ja-JP
 
3.1
C:\Program Files\Windows NT\TableTextService
 
2.9
C:\Program Files\Hyper-V\ja-JP
 
2.9
C:\Program Files\Windows Media Player
 
2.8
C:\Program Files\Hyper-V\6.2\ja-JP
 
2.7
C:\Program Files\Common Files\System\ado
 
2.6

以上、Get-ChildItemコマンドを利用したフォルダサイズの取得方法を紹介しました。

Get-ChildItemコマンドは、サブフォルダを深く掘り下げる場合でも、再起コードを呼び出すといった手間が必要ありません。簡単なオプションスイッチ(-Recurse)を付けるだけで、自動的に再起処理を行ってくれるという優れものです。

この他にも、特定のファイルを拡張子をキーとして抽出したり、ファイル構造だけではなく、レジストリの設定値を取得したりと様々な応用が可能です。ぜひ、チャレンジしてみてください。

著書の紹介欄

Hyper-Vで本格的なサーバー仮想環境を構築。仮想環境を設定・操作できる!

できるPRO Windows Server 2016 Hyper-V

◇Hyper-Vのさまざまな機能がわかる ◇インストールからの操作手順を解説 ◇チェックポイントやレプリカも活用できる Windows Server 2016 Hyper-Vは、仮想化ソフトウェア基盤を提供する機能であり、クラウドの実現に不可欠のものです。 本書では、仮想化の基礎知識から、Hyper-Vでの仮想マシンや仮想スイッチの設定・操作、プライベートクラウドの構築、Azureとの連携などを解説します。

初めてのWindows Azure Pack本が発売

Windows Azure Pack プライベートクラウド構築ガイド

本書は、Windows Azure PackとHyper-Vを利用し、企業内IaaS(仮想マシン提供サービス)を構成するための、IT管理者に向けた手引書です。試用したサーバーは、最小限度の物理サーバーと仮想マシンで構成しています。Windows Azure Packに必要なコンポーネントのダウンロード、実際にプライベートクラウド構築する過程を、手順を追って解説しています。これからプライベートクラウドの構築を検討するうえで、作業負担の軽減に役立つ一冊です。

ブログの著者欄

樋口 勝一

GMOインターネット株式会社

1999年6月GMOインターネットに入社。Windows Serverをプラットフォームとしたサービス開発から運用・保守まで幅広く担当。講演登壇や出版、ネット記事連載などでマイクロソフト社と強い信頼関係を構築。2007年より「マイクロソフトMVPアワード」を受賞し、インターネットソリューションのスペシャリストとして活躍。

関連記事