タイダログ

もっと怠けますか? (y/n)

PowerShell でフォルダサイズの一覧を取得する

PowerShell でフォルダサイズの一覧を取得する話です。ハードディスクがパンパンになった時に原因になっているフォルダを特定できます。
たぶん私が書いた最初の PowerShell スクリプトです。

C ドライブの容量が一杯

たしか社会人4年目。職場の先生から、パソコンの容量が一杯になっていて困っていると相談されました。エクスプローラで見ると C ドライブの容量が真っ赤っ赤。空き容量0。ファイルのコピーすらできないので仕事になりません。

ちなみに D ドライブはなく、普段からデータはファイルサーバ上の個人フォルダか共有フォルダに保存しています。

f:id:taidalog:20210221170720p:plain
C ドライブの空きがない(これは自宅のパソコン)

サイズが大きいフォルダを探す

サイズの大きいフォルダやファイルを見つけて、削除するなり移動させるなりしなければいけません。

まずは容量を占めているフォルダの特定から。上述の通り C:\Users\[ユーザ名]\ はほとんど空なので、怪しいのはC:\Program Files\C:\Windows\ でしょうか。

フォルダサイズを見るのが面倒

ところでフォルダサイズを見るのって面倒ですよね。ファイルのサイズはエクスプローラ上に出ますが、フォルダのサイズはプロパティからしか見られません。

f:id:taidalog:20210221182253p:plain
フォルダのサイズはエクスプローラに出ない

フォルダのプロパティの見方にはこんなのがあります。

  • (マウスで操作)フォルダを選択→右クリック→「プロパティ」
  • (キーで操作)フォルダを選択→ Alt + Enter

f:id:taidalog:20210221170826p:plain
プロパティを開く

f:id:taidalog:20210221170849p:plain
フォルダのプロパティ

ひとつひとつ、心を込めて Alt + Enter。サイズを確認。容量が大きいフォルダはサイズの計算に時間がかかります。しばらく待って容量が出たら、次のフォルダで Alt + Enter ......
4つ目くらいで込める心が尽きました。

PowerShell を使うことにする

VBA を始めて一年。これはプログラムでなんとかなると判断しました。さっそく VBA でなんとかしようと思ったのですが、

  • フォルダ内のファイルの一覧を取得する
  • それぞれのサイズを合計する
  • それを全てのフォルダに対して行う

というのが当時の私にはできそうにありませんでした。

FSO を使えばできるのはわかっていたのですが、やったことなかったし、もう遅い時間で疲れていたし……ごにょごにょ。

ということで別の方法を考え、Windows PowerShell を使うことに決めました。実はこんなこともあろうかとフォルダサイズの取得方法を調べていて、 PowerShell を使う方法を見つけていたのです。加えてちょうど PowerShell に興味を持ち始めた時期でもありました。

さっそくコンソールを開いてカタカタ。上手にできるかな?

結局勘と手作業

できませんでした。そりゃそうさ。比較的慣れている VBA でもできなかったことが初めての PowerShell でできるはずがない。

結局ネットで検索したりそれらしきフォルダをひとつひとつ心を込めて見たりして手作業で解決したのでした。ちなみに原因は pagefile.syshiberfil.sys でした。2つのファイルを削除してとりあえず終了。たしかそんな感じでした。

リトライ

このままじゃ終われない。私のプライドが許さない。何よりこのままでは次も手作業になる。それは嫌だ! もう心込めたくない!

ということで、ネットで調べなおしてスクリプトを書きました。こちらのサイトをほぼそのまま使わせていただきました。(肝心のコードは見られなくなっていますね)

www.gmo.jp

実際のコード

function Get-DirectorySizeList {

    $dirs = Get-ChildItem -Recurse -Force -Directory -ErrorAction SilentlyContinue
    [double]$size = 0
    $result = @()

    foreach ($d in $dirs) {
        $size = (Get-ChildItem $d.FullName -Force -File -ErrorAction SilentlyContinue | 
            Measure-Object -Property Length -Sum).Sum

        $result += [PSCustomObject]@{
            LastWriteTime = $d.LastWriteTime
            Length_GB = [Math]::Round($size / 1GB, 2)
            Length_MB = [Math]::Round($size / 1MB, 2)
            Length = $size
            FullName = $d.FullName
        }
    }

    return $result | Sort-Object -Property FullName
}

VBA との比較

VBA と違っていて戸惑ったこと

PowerShell の醍醐味であろうパイプラインの概念が全く分かっていませんでした。「左から来たものを右に受け流す」という動きはとってもムーディですね。

PSCustomObject も理解できず、まさに「よくわかんないけど動いた」という状態でした。

書式の面でも戸惑いました。たとえばパラメータとオプションの -の有無。

  1. Get-ChildItem -ErrorAction SilentlyContinue
  2. Get-ChildItem ErrorAction -SilentlyContinue
  3. Get-ChildItem ErrorAction SilentlyContinue

どれが正解か分かりませんでした。

他にも PowerShell のコマンドレットと .NET のメソッドとの間で、(), の有無で迷ったりしました。

VBA よりも好きなところ

コマンドレットがの命名規則が好みです。動詞-単数名詞 で統一してあります。一番いいのは単語を省略していないところです。そのおかげで比較的英語を読むようにコードを読めます。

それから配列に要素を追加するのが楽ですね。要素が増えすぎると重たくなるけど。

VBA だと、こう。

n = n + 1
ReDim Preserve arr(n)
arr(n) = 123

PowerShell なら、こう。

$arr += 123

一連の流れを終えて

そんなこんなで PowerShell に魅了された私は、業務では主に VBA を使いつつ PowerShell でも遊ぶという日々を送っていくのでした。

続編

一年後、このテーマに再挑戦しました。よかったらその話もどうぞ。

taidalog.hatenablog.com

さらにその続編です。こちらもぜひ。

taidalog.hatenablog.com

シリーズ最終作です。最後までどうぞ。

taidalog.hatenablog.com

参考

更新履歴

  • :2.0 へのリンクを追加 (2021/05/12)
  • :3.0 へのリンクを追加 (2021/06/10)
  • :3.0+1.0 へのリンクを追加 (2021/06/22)
  • 目次の位置を変更 (2021/09/09)
  • 目次の下に「こちらもどうぞ」を追加 (2021/09/09)
  • 参考」を追加 (2021/09/09)
  • 更新履歴」を追加 (2021/09/09)