PowerShellの勉強会

会社でPowerShellの勉強会を開く事になったので、その内容を考えながらアップしていく。

PowerShellとは

Microsoftが開発した次世代のWindowsシェル環境です。
従来Windows上でのシェル環境はCmd.exe(コマンドプロンプト)しかありませんでした。(CygwinなどのUnix互換環境は除く)コマンドプロンプトは簡易的な言語で条件分岐や繰り返し文などのプログラミング言語としてのサポートが不十分でした。

VBSやWSHなどのスクリプティング環境もありましたが、システム管理者などの非プログラマにとっては決して敷居が低くありませんでした。

その状況を解決するためにPowershellは開発されました。
コマンドプロンプトのように簡単に使用でき、本格的なプログラミング言語並みの表現力も持ち、新しいアプリケーションプラットフォームである「.NET Framework」に対して完全なアクセスのできるシェル環境として。

初めてのPowerShell

まずはお約束のHelloWorldから

PS > echo "Hello, World"

「echo」はコマンドプロンプトでもおなじみのコマンドです。
また、以下のコマンドも同じ意味を持ちます。

PS > write "Hello, World"
PS > Write-Output "Hello, World"

PowerShellではコマンドに別名(Alias)を付けることができます。
この場合、「Write-Output」というコマンドに「echo」と「write」というAliasが設定されています。またPowerShellではコマンドの事をコマンドレット(Cmdlet)と呼びます。

ちなみに、Aliasが実際にどのCmdletに割り当てられているかを調べるには以下のようにします。

PS > Get-Alias echo

CommandType     Name                                           Definition
-----------     ----                                           ----------
Alias           echo                                           Write-Output

その逆に、Cmdletから割り当てられているAliasを調べるには以下のようにします。

PS > Get-Alias | ? { $_.Definition -eq "Write-Output" }
CommandType     Name                                           Definition
-----------     ----                                           ----------
Alias           write                                          Write-Output
Alias           echo                                           Write-Output

PowerShellにはCmdletの他に関数(function)があります。
Cmdletは通常C#VB.NETなどの.NET Frameworkに対応した高級言語で作成しますが、functionはPowerShell言語で作成します。簡単な処理などはfunctionで記述すると覚えておくといいでしょう。

コマンドプロンプト的な使い方

カレントディレクトリのファイルを一覧表示する。

PS > dir

フィルタをかける。

PS > dir *.txt

ディレクトリも対象にする。

PS > dir -recurse

コマンドプロンプトと同じようにPowerShellでもパイプラインが使用できます。
結果をページングする。

PS > dir | more

結果をソートする。

PS > dir | sort -descending

特定の条件に一致するものだけ表示する。

PS > dir | where { $_.Extension -eq "txt" }

コマンドプロンプトではパイプラインを流れるのは唯のテキストデータでした。
しかし、PowerShellではパイプラインを.NETのオブジェクトが流れます。
例えば「dir」では「FileInfo」型と「DirectoryInfo」型を含む「object」型の配列が流れます。

Cmdletのヘルプを表示する

PS > man dir

よく使うCmdlet

Alias Cmdlet 説明
dir Get-ChildItem カレントディレクトリにファイル/ディレクトリを列挙
cd Set-Location カレントディレクトリを変更
mkdir (関数) ディレクトリを作成
rmdir Remove-Item ディレクトリを削除
del Remove-Item ファイルを削除
copy Copy-Item ファイル/ディレクトリのコピー
move Move-Item ファイル/ディレクトリの移動
pwd Get-Location カレントディレクトリを取得
ps Get-Process プロセスの一覧を列挙
kill Kill-Process プロセスを停止

オブジェクト操作系

Alias Cmdlet 説明
%, foreach ForeEach-Object オブジェクトを順番に処理する
?, where Where-Object 条件に一致するオブジェクトを取得する
sort Sort-Object オブジェクトを並べ替える
group Group-Object オブジェクトをグループ化する
select SelectObject オブジェクトの特定の属性のみ取得する

プログラミング言語としてのPowerShell

比較演算子

演算子 説明
-eq 等しい
-ne 等しくない
-gt 大なり
-ge 大なりイコール
-lt 小なり
-le 小なりイコール
-like 文字列比較(ワイルドカードあり)
-match 正規表現マッチング
-contains リストに含まれるか

表現
文字列 "Hello"
数値 1
真偽値 $true, $false
配列 @(1, 2, 3)
連想配列 @{Hoge=1, HogeHoge=2}

変数

PS > $s = "Hello"
PS > echo $s
Hello

制御構文

  • 条件分岐
if(条件) {
    コードブロック
}
  • 繰り返し
foreach(要素 in コレクション) {
    コードブロック
}

関数

function printMessage([string]$message) {
    echo $message
}

実用的なスクリプト

Q. VisualStudioで開発したソースを圧縮するのに「bin」や「obj」フォルダが邪魔です。
このフォルダをさくっと削除したいです。
A.

PS > dir -recurse -include bin,obj | del -recurse -force


Q. エロ画像を大量にダウンロードしてきました。でもファイル名がばらばらで集中できません。
ファイル名を連番にしたいけど、手でやるのはめんどくさいし・・・。
A.

PS > $index = 0
PS > dir *.jpg | foreach { $_.CopyTo("c:\エロ画像\{0:00#}.jpg" -f $index++) }


Q. 僕のマシンで時々余計なプロセスが立ち上がって残ったままになっています。
メモリをばか食いするので、毎回手動で削除しています。どうにかなりませんか?
A.

PS > ps プロセス名 -ErrorAction SilentlyContinue | kill

あとはこのスクリプトをタスクスケジュールに仕込んで定期的に実行すればいいでしょう。

スクリプトファイルの記述

PowerShellスクリプトはテキスト形式で記述し、拡張子を「ps1」にします。
デフォルトではPowerShellスクリプトファイルを実行できないので、権限を変更する必要があります。
PowerShellを起動して、以下のCmdletを実行してください。

PS > Set-ExecutionPolicy -executionPolicy RemoteSigned

PowerShellスクリプトは以下のように実行します。

PS > ./ファイル名