前回は、PowerShell ぽい使い方を解説しました。
PowerShell 的な使い方(1)
http://www.vwnet.jp/Windows/PowerShell/2018040502/GettingStartedWithPowerShell-02.htm
今回は実践的な PowerShell の使い方を解説します。
デフォルトのコマンドレット出力は、代表的なプロパティがテーブル表示されますが、必要なプロパティが表示されていないとか、出力が長くて途中で切れているとか残念な事も良くありますよね。
そんな時は、出力を一工夫するとぐっと使いやすくなります。
Format-Table は、指定したプロパティをテーブル表示しますので一覧で見たいときに便利です。-AutoSize を使うと項目幅が自動調整されます。
Get-ChildItem C:\Windows\System32\drivers\etc\ | Format-Table FullName, LastWriteTime, Length -AutoSize |
Format-List は、指定したプロパティをリスト表示しますので長いプロパティを見たいときに便利です。
Get-ChildItem C:\Windows\System32\drivers\etc\ | Format-List FullName, LastWriteTime, Length |
Select-Object は、対象となるプロパティを選択し、必要なオブジェクトに絞るのに使います。
全てのプロパティを指定する場合は、* を使います。
Get-ChildItem C:\Windows\System32\drivers\etc\ | Select-Object * |
Out-GridView はグリッドビューに格納します。グリッドビューは簡単なデータ操作が出来ます。
Format-Table、Format-List と違い、格納するプロパティを指定できないので、Select-Object
でプロパティを絞ります。
Select-Object せずに Out-GridView に渡すと、default
表示されるプロパティだけが対象になります。
Get-ChildItem C:\Windows\System32\drivers\etc\ | Select-Object FullName, LastWriteTime, Length | Out-GridView |
値だけを扱うのであればこれまでの表示方法で事足りますが、人が有意文として読む事を想定した場合には物足りないですね。
そんな時は、テキスト整形をします。
例えば以下のような有意文にするケースで説明しましょう。
只今の気温は 23 ℃、湿度は 45 % です。 |
既に値は以下変数に格納されているとします。
$Temperature = 23 $Humidity = 45 |
PowerShell の文字列は、ダブルクォーテーションで囲むと変数が展開される仕様を使います。
$Sentence = "只今の気温は $Temperature ℃、湿度は $Humidity % です。" |
文字列としてつなげていく事も出来ます。
$Sentence = "只今の気温は " + $Temperature + " ℃、湿度は " + $Humidity + " % です。" |
あるいは、こんな方法でもイケます。
$Sentence = "只今の気温は " $Sentence += $Temperature $Sentence += " ℃、湿度は " $Sentence += $Humidity $Sentence += " % です。" |
プログラミングをした事ある方ならフォーマットは出来ないの? と思われますよね。
もちろん出来ます。
$Sentence = "只今の気温は {0} ℃、湿度は {1} % です。" -f $Temperature, $Humidity |
大かっこ { } 内の数字が引数の並び順です。
項目の表示幅は「{n,s}」のように s で表現します。s だけだと右揃え、-s にすると左揃えになります。
数値を編集する場合は「{n,s:format}」で表現します。
もう一つのフォーマット方法は、.NET framework String クラスの Format メソッドを使う方法です。
$Sentence = [String]::Format("只今の気温は {0} ℃、湿度は {1} % です。", $Temperature, $Humidity) |
大かっこ {} 内は -f と同じで、幅指定、右寄せ左寄せ、編集ができます。
フォーマットする時にでよく使われる編集にはこんなのがあります。
カンマ編集 | #,# |
固定長にしてリーディングゼロをつける | 0000000 |
少数以下桁数指定 | 0.00 |
4桁の小文字16進数 | x4 |
4桁の大文字16進数 | X4 |
これを使うとこんな感じに編集できます。
$Sentence = "只今の気温は {0:0.00} ℃、湿度は {1:0.00} % です。" -f $Temperature, $Humidity |
PowerShell は様々なものが簡単にハンドリングできるので、ツールとしてとても使い勝手があります。
PowerShell といえば、コマンドレッドですよね。
コマンドレッドはオブジェクトを出力するので、必要なプロパティを使ったり、メソッドを使って様々なことができます。
コマンドレットとオブジェクトについては既に説明済みなので、これ以上の説明は割愛します。
ipconfig 等の一般的な DOS コマンドは、オブジェクトではなく、テキストしか出力できません。
コマンドレットと違い、一般コマンドが出力した内容をハンドリングするにはちょっとした工夫が必要になります。
一般コマンドが出力形式は、一行が文字列型(String)の配列になっています。
例えば、ipconfig の出力のうち「IPv4」が含まれている行を抽出する場合は、正規表現検索をする Select-String コマンドレットを使い以下のようにします。
ipconfig | Select-String IPv4 |
これで「IPv4」が含まれている行が取れました。
このうち IP アドレスが欲しい場合は、「:」で分割し、2つ目の要素を取り出します。
文字列を指定文字で分割するには -split 演算子を使用し、分解された1番目の要素が目的のIPアドレスです。(0から数えるので、1つ目の要素は0番目、2つ目は1番目の要素と表現されます)
オブジェクト配列なので、ForEach-Object コマンドレットの Alias である % で要素分解し、各要素に対して分割します。
こんな感じですね。
ipconfig | Select-String IPv4 | % {($_ -Split ":")[1]} |
このままでは、先頭に余分な空白が含まれているので、Trim メソッドで余分な空白を取り除きます。
ipconfig | Select-String IPv4 | % {($_ -Split ":")[1]} | %{$_.Trim()} |
これで IPv4 アドレスだけを取り出すことができました。
PowerShell でよく扱うのがファイルシステムです。
指定したフォルダやファイルそのものを情報を得る場合は、Get-Item あるいは Get-ItemProperty を使います。
フォルダを指定する場合に絶対 Path を使う場合は、ドライブレターを含めた Full Path
を指定します。
Get-Item C:\Windows\ |
カレントディレクトリを移動するには、Set-Location を使います。コマンドプロンプトに慣れている方であれば、Set-Location の Alias である cd の方が馴染みがありますね。
cd C:\Windows\ |
相対 Path を指定する場合、PowerShell ではカレントディレクトリを「.\」と表現しますので、System32 サブディレクトリを指定する場合は以下のようにします。
cd .\System32\ |
1つ上のディレクトリは「..」なので、カレントディレクトリから見て1つ上のディレクトリは「.\..」と表現します。
cd .\.. |
指定したディレクトリ下にあるファイルやディレクトリ情報を得る場合は、Get-ChildItem を使います。
Get-ChildItem .\System32\drivers\etc\ |
Windows の共有をアクセスする場合は、\\サーバー名\共有名 の UNC がポピュラーですね。
PowerShell
でもアクセス権のある共有であれば UNC でアクセスすることが可能です。
Get-Item \\file01\common\ |
UNC でうまくアクセスできない時は、「Filesystem::」をつけるとうまくアクセスできることがあります。
Get-Item Filesystem::\\file01\common |
問題は権限が無い共有にアクセスする場合です。
アクセス権の無い UNC にアクセスするとエラーになってアクセスすることができません。
このような場合は、昔ながらの net use コマンドを使って認証を受ける手があります。
net use \\192.168.33.63 パスワード /user:ホスト名\アカウント(ドメイン名\アカウント) |
net use コマンドを使って認証を受けると $IPC で認証が取れているのがわかります。
共有を使い終わったら、net use /delete で接続を解除します。
net use /delete * /yes |
net use を使うより、xxx-PSDrive コマンドレットを使うのが PowerShell らしいと言えるでしょう。
共有を接続するには、New-PSDrive を使って以下のようにします。
New-PSDrive -Name 接続名 -Root UNC -PSProvider FileSystem -Credential ホスト名\アカウント(ドメイン名\アカウント) |
New-PSDrive で接続した共有にアクセスするには、接続名: にアクセスします。
Get-Item Private: |
接続を解除するときは、Remove-PSDrive で切断します。
レジストリも、ファイルシステムと同様に Get-Item、Get-ItemProperty、Get-ChildItem、Set-Location が使えますし、権限があれば編集も可能です。
ハイブはデフォルトで HKEY_CURRENT_USER と HKEY_LOCAL_MACHINE が割り当てされていますが、これ以外のハイブも必要に応じて New-PSDrive で割り当てしてアクセスします。
ハイブ | 割り当て | 備考 |
HKEY_CURRENT_USER | HKCU: | 標準割り当て済み |
HKEY_LOCAL_MACHINE | HKLM: | 標準割り当て済み |
HKEY_CURRENT_CONFIG | HKCC: | New-PSDrive -Name HKCC -PSProvider Registry -Root HKEY_CURRENT_CONFIG |
HKEY_CLASSES_ROOT | HKCR: | New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT |
HKEY_USERS | HKU: | New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS |
例えば、HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows をカレントにし、直下を確認するには場合は以下のようにします。
Set-Location
HKLM:\SOFTWARE\Policies\Microsoft\Windows Get-ChildItem |
フルパスを指定する場合は以下のようにします
Get-ChildItem HKLM:\SOFTWARE\Policies\Microsoft\Windows |
割り当て状況は Get-PSDrive で確認できます。
WMI ハンドリングは、WMI クラスをオブジェクトにしてハンドリングします。
例えば、OS 名を見る場合は Win32_OperatingSystem クラスの Caption プロパティを見ます。
$Win32_OperatingSystem = Get-WmiObject -Class
Win32_OperatingSystem $Win32_OperatingSystem.Caption |
取ってきた物はオブジェクトなので、プロパティだけではなくメソッドもあるので WMI に対しての操作も可能です。
.NET のハンドリングは、スタティックメソッドを扱う場合と、クラスをオブジェクトにしてハンドリングする方法の2種類があります。
スタティックメンバーを使う場合は、以下ののようにします。
[クラス]::メソッド(引数) |
例えば、System.Math の Pow メソッド(べき乗を求めるスタティックメソッド)を使う場合は以下のようにします。
$a = [System.Math]::Pow(5,3) |
クラスをオブジェクトにする場合は、New-Object を使います。コンストラクタに渡す引数をセットしない場合は () を省略します。
New-Object クラス(コンストラクタに渡す引数) |
例えば、System.Random を使って 1000 以下のランダム値を求める場合は以下のようにします。
$a = New-Object System.Random $a.Next(1000) |
New-Object した場合、オブジェクトが Dispose メソッドを持っていることがあります。
この場合は、使用した後に Dispose してオブジェクトを開放するとメモリーの節約になります。
明示的に Dispose しないと動作がおかしくなるクラスもあるので、必ず Dispose で後始末するのがおすすめです。
PowerShell はデータファイルのハンドリングも得意です。
テキストファイルのハンドリング コマンドレットは沢山ありますが、僕が良く使う Get-Content / Set-Content で説明します。
テキストファイルを読む場合は、以下のようにします。
受け取り変数 = Get-Content -Path ファイルパス |
文字コードを指定して読む場合は、-Encoding オプションを使います。
日本語環境で SJIS として読む場合は、-Encoding Default を指定します。
読み込んだデータは、文字列の配列になっているので、Where-Object(?)、ForEach-Object(%) でぐるぐる回して処理します。
ファイルの書き込みは、以下のようにします
Set-Content -Path ファイルパス -Value セットするデータ |
文字コードを指定する場合は、Get-Content と同様に -Encoding で指定します。
CSV はよく使われるので専用のコマンドレットがあります。
CSV ファイルを読む場合は、以下のようにします。
受け取り変数 = Import-Csv -Path ファイルパス |
文字コードは -Encoding で指定します、
CSV ファイルはオブジェクトの配列になっているので、通常の PowerShell オブジェクトと同様に扱うことができます。
CSV のヘッダー(1行目)がオブジェクト名になるので、ヘッダーのついていない CSV はハンドリングできません。
CSV ファイルの書き込みは、リダイレクトを使って以下のようにします
セットするデータ | Export-Csv -Path ファイルパス |
データに日本語が含まれているときは、-Encoding Default で SJIS を指定するか、-Encoding UTF8 で UTF-8 を指定します。
CSV は2次元配列なので、2次元以外のデータをファイルにハンドリングする場合 JSON を使います。
JSON は WebAPI でよく使われるデータ形式なので、Web Service Client を実装する場合には必須のデータ形式です。
JSON はテキストファイルとしてハンドリングし、ConvertFrom-Json と ConvertTo-Json で JSON 変換をハンドリングします。
JSON データは、一旦テキストファイルとして読んで、ConvertFrom-Json にリダイレクトしてオブジェクトの配列にします。
$JsonData = Get-Content -Path C:\Test\test.json $ObjectData = $JsonData | ConvertFrom-Json |
データはオブジェクト配列になっていますが、JSON そのものにデータの型が無いので、プロパティは値を見て型が自動適用された状態になっています。
出力時は、ConvertTo-Json で JSON 形式のテキストに変換し、テキストファイルとして出力します。
$JsonData = $ObjectData | ConvertTo-Json Set-Content -Path C:\Test\test2.json -Value $JsonData |
Get-Content でテキストファイルとして読んで、[xml] で XML にキャストします。
[xml]$XmlData = Get-Content "C:\Test\test.xml" |
XML はピリオドで階層をたどれます。
プロパティに文字列がセットできます(文字列以外は NG)
XML ブラウザー(Web ブラウザー等)で構造を見た方が操作しやすいです。
メソッドがあるので、メソッドでの操作も可能です。
例えば、要素を追加するのであれば CreateElement/AppendChild、属性の追加は SetAttribute を使います(詳しい情報は割愛するのでクグって w)
Save メソッドで出力します
$XmlData.Save("C:\Test\Test2.xml") |
PowerShell プロンプトからうまく扱うことができない DOS コマンドは、cmd モードで操作します。
例えば、実行ファイルの存在場所を確認する where は PowerShell の Where-Object のエイリアスとかぶっているので where コマンドはそのままでは使えません。
そんな時は cmd モード(僕がつけた呼称)で where を実行します。
「cmd」で cmd モードに入って where
を実行(プロンプトが変わるので、それでモード確認)
その後「exit」で cmd モードから抜けます
cmd /c で where コマンド実行します
cmd /c where notepad |
今日から使う PowerShell
http://www.vwnet.jp/Windows/etc.asp#GettingStartedWithPowerShell
Copyright © MURA All rights reserved.