CSV があれば、(コンソールを閉じても)全部やり直せる。
2021/06/20 CSV出力した際にフォルダひとつ分の結果しか出力できなかった件について、コードを修正しました。
これまで、Windows PowerShell でフォルダサイズの一覧を取得する方法を紹介してきました。取得したデータを変数に格納してソートすれば、容量を食っているフォルダを特定できます。
ですが、コンソール(PowerShell の画面)を右上の×や exit
で閉じると変数の中身は消えます。まあ当然です。当然なのですが、うっかり閉じてしまうこともあります。うっかり exit
することはないかもしれませんが、うっかり Alt+F4
や Alt+Space+C
などすることはあります。あります。Alt+Space+X
しようとしたときなんか特に。
ということで、フォルダサイズの一覧を CSV ファイルに保存して、コンソールを閉じた後でも利用できるようにしましょう。
この話の続きです。
CSV に出力して結果を保存する
PowerShell で CSV 出力するには、Export-Csv
コマンドレットを使うと便利です。出力したいデータをパイプライン (|
) 等で渡すだけです。
one-liner
フォルダサイズの取得方法は前回と全く同じです。
https://taidalog.hatenablog.com/entry/2021/03/16/053000#コード
CSV への出力手順は、
- 保存先の CSV ファイルのパスを作る
- フォルダサイズの一覧を取得する
Export-Csv
で出力する
だけです。こうします↓。
$csvPath = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "DirectorySizes$((Get-Date).ToString('yyyy-MM-dd_HH-mm-ss')).csv"; Get-ChildItem -Recurse -Directory | ForEach-Object {$childItems = @(Get-ChildItem -LiteralPath $_.FullName -File); [long]$totalLength = ($childItems | Measure-Object Length -Sum).Sum; [PSCustomObject]@{Length = $totalLength; LengthMB = [Math]::Round($totalLength / 1MB, 2); LengthGB = [Math]::Round($totalLength / 1GB, 2); Count = $childItems.Length; FullName = $_.FullName}} | Export-Csv -Path $csvPath -Encoding utf8 -Append -NoTypeInformation
最初の
$csvPath = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "DirectorySizes$((Get-Date).ToString('yyyy-MM-dd_HH-mm-ss')).csv";
で保存先の CSV ファイルのパスを作っています。[Environment]::GetFolderPath("MyDocuments")
がユーザーのドキュメントフォルダを表していますので、保存先はドキュメントフォルダで、ファイル名は DirectorySizes_<yyyy-MM-dd_HH-mm-ss 形式の日時>.csv
です。
最後の
| Export-Csv -Path $csvPath -Encoding utf8 -Append -NoTypeInformation
で CSV 出力をしています。
-Append
パラメータを忘れてはいけません。これがないと前のデータを新しいデータで上書きしてしまうので、結果的に最後のフォルダのサイズしか CSV ファイルに残りません。
function
function (Measure-Directory
) のコードは、前回同様 Gist でご覧ください。開いたページでスクリプトをダウンロードできます。
get_the_list_of_directory_size.psm1 · GitHub
モジュールファイル (.psm1) の使い方はお調べください。Set-ExecutionPolicy
と Import-Module
ができれば OK です。
こちらの出力手順や保存先、ファイル名も one-liner と同じです。
$csvFilePrefix = 'DirectorySizes_' $datetimeFormat = 'yyyy-MM-dd_HH-mm-ss' $csvExtension = '.csv' $csvPath = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "$($csvFilePrefix)$((Get-Date).ToString($datetimeFormat))$($csvExtension)" Get-ChildItem -Recurse -Directory | Measure-Directory | Export-Csv -Path $csvPath -Encoding utf8 -Append -NoTypeInformation
CSV のデータを変数に格納して再利用する
ここまでの手順で結果を CSV ファイルに保存できました。今度は、PowerShell で再び操作できるようにデータを変数に格納しましょう。CSV ファイルからの取り込みは Import-Csv
コマンドレットです。ソートはそのまま Sort-Object
コマンドレットです。
$csvPath = 'CSV ファイルへのパス' $importedDirectorySize = Import-Csv -Path $csvPath -Encoding utf8 $importedDirectorySize | Sort-Object -Property Length -Descending | Format-Table
結果はこの通り。
Length LengthMB LengthGB Count FullName ------ -------- -------- ----- -------- 998511 0.95 0 1 D:\Users\taidalog\history\translation\Traget text 9963 0.01 0 19 D:\Users\taidalog\Documents\notes 9963 0.01 0 19 D:\Users\taidalog\Documents\3.33 99425810 94.82 0.09 10 D:\Users\taidalog\Music\Media\Music\ 993041493 947.04 0.92 23 D:\Users\taidalog\Downloads 988829 0.94 0 5 D:\Users\taidalog\history\maps 98804736 94.23 0.09 1 D:\Users\taidalog\Documents\Outlook Files 98778 0.09 0 7 D:\Users\taidalog\MeasureExcelFunction\test 9849 0.01 0 6 D:\Users\taidalog\BackupDiskData 9834 0.01 0 7 D:\Users\taidalog\Documents\source\repos\HIUC1\HIUC1\x64\Debug
あら? 並び順がおかしいのでは? 9963 が 99425810 の上に来ている。
君が何を言っているのか分かんないよ!
CSV の数字を数値に変換する
$importedDirectorySize
の中身は、CSV からインポートした文字列です。そう、文字列です。Length プロパティも文字のままです。「数字」と「数値」の違いですね。
これを [long]
でキャストします。
$importedDirectorySize | Sort-Object -Property {[long]$_.Length} -Descending | Format-Table
Length LengthMB LengthGB Count FullName ------ -------- -------- ----- -------- 9656763028 9209.41 8.99 121 D:\Users\taidalog\Music\Media\Applications 993041493 947.04 0.92 23 D:\Users\taidalog\Downloads 860611018 820.74 0.8 42 D:\Users\taidalog\Music\Media\Music\Bulfinch 694238574 662.08 0.65 40 D:\Users\taidalog\Music\Media\Videos 630599256 601.39 0.59 3 D:\Users\taidalog\Downloads\F_20170912 581483418 554.55 0.54 16 D:\Users\taidalog\Documents\SCAN MG6730\MY_BA01 581483418 554.55 0.54 16 D:\Users\taidalog\history\SCAN MG6730\MY_BA01 566058060 539.84 0.53 33 D:\Users\taidalog\history\school\h29 429769935 409.86 0.4 3 D:\Users\taidalog\history\University\Library Supporter 398568754 380.1 0.37 166 D:\Users\taidalog\Music\Media\Music\italian_basic_a
ふう。コンソール上は文字列のままですが、ソートの際には数値に変換できています。
Sort-Object
コマンドレットの -Property
パラメータはスクリプトブロックを指定できるので、{[long]$_.Length}
でよいみたいです。
Microsoft のドキュメントにもありました。
まとめ
落ちが思いつかないので14年くらい寝ます。
続編
こちらもぜひ。
参考
- powershellでCSV等の区切り文字があるファイルの数値列の合計を計算する - Qiita
- スクリプトブロックパラメータのススメ - PowerShell Scripting Weblog
- Sort-Object (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Docs