2019年3月21日木曜日

PowerShellで抽出したオブジェクトに、自分でプロパティ名を付けたい

PowerShellでは、SELECT-OBJECT(SELECTと省略可能)でオブジェクトから好きなプロパティ(列名)だけを選ぶ事が可能です。

たとえば、GET-CHILDITEMでもって、ファイル/フォルダの一覧を取得した時に、数多くのプロパティ(列名)の中から3つだけ、NameとLengthとPsIsContainerだけを選びたい!!というような時です。

これだけで終わるのであれば、べつに何の事は無いわけですが、たとえばこの例ですと「Lengthプロパティはバイト単位なのでKB単位に計算し直したい」という時もあろうかと思います。

こんな時には、SELECT-OBJECTコマンドレットの中に {[Math]::Ceiling($_.Length/1024)}と書くだけじゃん?となるわけですが、なんと計算式がそのままプロパティ名に変わってしまうのです。


■計算式がそのままプロパティ名になる


#ファイルの一覧を取得
$V = GET-CHILDITEM C:\TEMP

#ファイルの一覧から、Name、LenthをKB単位で計算、PSIsContainerプロパティをSELECT
$V | SELECT-OBJECT Name,{[Math]::Ceiling($_.Length/1024)}, PSIsContainer



C:\>$V | SELECT-OBJECT Name,{[Math]::Ceiling($_.Length/1024)}, PSIsContainer

Name                        [Math]::Ceiling($_.Length/1024) PSIsContainer
----                        ------------------------------- -------------
.vscode                                                   1          True
Program                                                   1          True
CHECKDIGIT.js                                             3         False
CODE_SAMPLE_EBCDIC.DAT                                    1         False
CODE_SAMPLE_SJIS.DAT                                      1         False
configuration.xml                                         1         False
FILELIST.CSV                                             22         False
FILELIST2.CSV                                            18         False
FILE_LIST.TXT                                             2         False
FREE.PS1                                                  1         False
mori.txt                                                  1         False
MY_SETTING.xml                                            1         False
MY_SETTING_TEMPLATE.xml                                   1         False
NodeJs - ショートカット.lnk                               2         False
OuterTest.js                                              1         False
Regex.js                                                  2         False
SAMPLE_SJIS.DAT                                           1         False
SAMPLE_UTF8N.DAT                                          1         False
setup.exe                                              5068         False
SQL1 - コピー (2).js                                      2         False
SQL1 - コピー.js                                          2         False
SQL1.js                                                   4         False
TEST.CSV                                                  1         False
TEST.html                                                 1         False
TEST.js                                                   1         False
test.ps1                                                  0         False
test.sql                                                  0         False
TEST.TXT                                                130         False
TEST.xlsx                                                10         False
TEST000.js                                                1         False
TEST2 - コピー.html                                       2         False
TEST2 - コピー.js                                         4         False
TEST2.html                                                2         False
TEST2.js                                                  6         False
test_test.txt                                             0         False
unEditor_Shift_JIS.txt                                    1         False
ナレッジベース.xlsx                                      35         False
手順.txt                                                  1         False



↑このように、Lengthを÷1024し端数を切り上げる事でKB=キロバイト単位に再計算したわけですが、計算式がそのまんまプロパティ名になってしまいます。

この場で結果を目で確認して終わり・・・というのであれば別に気にしなくとも良い(計算式が分かる分むしろ良い所もある?)のですが、このまま次の処理にチェーンしたり、結果をOUT-FILEコマンドレットでファイル書き出ししたりすると、プロパティ名は分かりやすい名前を付けたいものです。


■プロパティ名は連想配列で付けられます



#ファイルの一覧を取得
$V = GET-CHILDITEM C:\TEMP

#ファイルの一覧から同じくSELECTした内容に自分でプロパティ名を付けます。
$V2 = ($V | SELECT-OBJECT @{Name="名前";Expression={$_.Name}},@{Name="容量KB";Expression={[Math]::Ceiling($_.Length/1024)}}, @{Name="フォルダ";Expression={$_.PSIsContainer}})

#自分で付けたプロパティ名で抽出する。
$V2 | ?{$_.名前 -match "TEST" -and $_.容量KB -gt 1}




C:\>#ファイルの一覧を取得
C:\>$V = GET-CHILDITEM C:\TEMP
C:\>
C:\>#ファイルの一覧から同じくSELECTした内容に自分でプロパティ名を付けます。
C:\>$V2 = ($V | SELECT-OBJECT @{Name="名前";Expression={$_.Name}},@{Name="容量KB";Expression={[Math]::Ceiling($_.Length/1024)}}, @{Name="フォルダ";Expression={$_.PSIsContainer}})
C:\>
C:\>#自分で付けたプロパティ名で抽出する。
C:\>$V2 | ?{$_.名前 -match "TEST" -and $_.容量KB -gt 1}

名前                容量KB フォルダ
----                ------ --------
TEST.TXT               130    False
TEST.xlsx               10    False
TEST2 - コピー.html      2    False
TEST2 - コピー.js        4    False
TEST2.html               2    False
TEST2.js                 6    False

↑どうすれば自分でプロパティ名をつけられるのかというと、連想配列を使います。

本来のプロパティ名を列挙する場所に、連想配列@{Name="つけたいプロパティ名";Expression=計算式}を書くと、自分で付けたプロパティ名を使う事が出来るという寸法であります。

さすがに連想配列を書くとコマンドがとても長くなってしまうので、対話式の入力は若干辛くなってしまうのが難点ですが・・・。

もちろん、一度付けたプロパティ名は次の処理にチェーンしても使えます。

連想配列はこのようにコマンドレットのパラメーター指定に使ったりするので、書式を覚えておくのはおすすめです。