[PowerShell] 古いバージョンのモジュールを一括削除する

Windows PowerShell

しばたです。

PowerShellのモジュールはUpdate-Moduleで更新した際に過去バージョンを残す仕様となっています。
例えば私の開発PCでAWSPowerShell.NetCoreモジュールのインストール状況を確認すると、

# インストール済みの AWSPowerShell.NetCore モジュール全バージョンを取得
Get-InstalledModule -Name AWSPowerShell.NetCore -AllVersions

この様にVer.3.3.522、Ver.3.3.542、Ver.3.3.553と3つのバージョンがインストールされていることがわかります。

古いバージョンのモジュールを一括削除する

この仕様は新しいバージョンに不具合があった場合に古いバージョンに切り戻せる様にするためのものですが、古いバージョンが溜まり続けるとディスク容量を圧迫しますので、最新バージョンに問題がなければ古いバージョンを消したくなるのが人情です。

モジュールを削除するにはUninstall-Moduleを使用しますがバージョンを明示しない場合は最新バージョンを削除する仕様となっています。
このため、最新バージョン以外を削除したい場合は最初に以下の様に最新バージョン以外のモジュールを抽出し、

# 最新バージョン以外のモジュールを取得
Get-InstalledModule -Name AWSPowerShell.NetCore -AllVersions | 
    Sort-Object -Property Version -Descending |
    Select-Object -Skip 1

(最新バージョン以外のモジュールを抽出)

パイプラインでUninstall-Moduleを呼び出してやる必要があります。

# 今回はテストなので Uninstall-Module に -Confirm を付けています
Get-InstalledModule -Name AWSPowerShell.NetCore -AllVersions | 
    Sort-Object -Property Version -Descending |
    Select-Object -Skip 1 |
    Uninstall-Module -Confirm

(上図では最新のVer.3.3.553以外を削除しようとしているのがわかります)

これで最新バージョン以外のモジュールを削除できました。

【重要】やってはいけない方法

この記事を書くきっかけとなったのですが、私はしばらく以下の様にGet-InstalledModuleではなくGet-Moduleを使ってモジュールの削除をしようとしてました。

#
# ※やってはいけない※
#   Get-Module と Uninstall-Module を併用する
#

# 今回はテストなので Uninstall-Module に -Confirm を付けています
Get-Module -Name AWSPowerShell.NetCore -ListAvailable | 
    Sort-Object -Property Version -Descending |
    Select-Object -Skip 1 |
    Uninstall-Module -Confirm

この場合はパイプラインを渡るオブジェクトの型が悪いためパラメーターバインドが上手くいかず期待した動作になりません。
常に最新バージョンのモジュールの削除を試みてしまいます。

(パイプラインで渡されるオブジェクトの型が悪く、常に最新バージョンであるVer.3.3.553の削除を試みてしまっている)

Get-Moduleを使ってモジュールを削除する場合はパイプラインからの入力(InputObject)を使わず、以下の様に個々のパラメーターを指定する様にしてください。

#
# ※回避策※
#   Uninstall-Moduleにパイプラインからオブジェクトを渡さずにパラメーターを個別に指定する
#

# 今回はテストなので Uninstall-Module に -Confirm を付けています
Get-Module -Name AWSPowerShell.NetCore -ListAvailable | 
    Sort-Object -Property Version -Descending |
    Select-Object -Skip 1 |
    ForEach-Object { Uninstall-Module -Name $_ -RequiredVersion $_.Version -Confirm }

(-RequiredVersionパラメーターを指定してバージョンを明示しているので期待した動作になる)

最後に

ざっとこんな感じです。
ちょっとしたTipsですがGet-InstalledModuleGet-Moduleの使い方を間違えてしまうと大変なことになってしまうのでご注意ください。