PowerShell ことはじめ

概要

  • PowerShell は、.NET Framework を基盤にしたコマンドラインシェルであり、かつスクリプト環境である
  • コマンドの出力結果をフィルタするときは、grep ではなく、Where-Object コマンドレットを使う
  • ヘルプに情報が充実しているので、help コマンドなどで調べていれば、何となく使い方はわかりそう


コマンドラインシェルとして使ってみる

コマンドラインシェルとして見た場合、コマンドの実行結果の実体は .NET Framework のオブジェクトであり、その点で従来のシェル(cmd.exe やUnix のシェルなど)と大きく異なる。

ためしにdir コマンドを使ってみる。すると PowerShell でも、次のように使うことができる。

PS C:\Users\daisuke> dir


    ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Users\daisuke


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2009/03/26     20:32            .nbi
d----        2009/03/26     20:35            .netbeans
…略…

出力様式がこれまでとは違うけど、それはまあ置いておくとして、更に PowerShell では、次のような書き方が可能になる。

PS C:\Users\daisuke> (dir).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

「(dir)」の次のピリオドは、オブジェクトのメソッドやフィールドにアクセスするための構文。Java や C# をはじめとする各種言語と同様。

つまり、この表現は、dir コマンドが返してきたオブジェクトのGetType メソッドを実行せよという意味で、このように、PowerShell では、コマンドの結果そのものをオブジェクトとして扱っている。

なお、GetType メソッドは、そのオブジェクトの型を取得するためのものであって、.NET Framework の基底クラスである System.Object クラスから継承されているため、どのコマンドの結果に対しても使うことができる、と思う。

ところで上記の例では、dir コマンドが返してきたオブジェクトの型は、System.Array 型らしいことがわかる。どうやら配列らしいので、それなら添字を使うことで各要素にアクセスできるような気がするけど、実際できてしまう。

PS C:\Users\daisuke> (dir)[0]


    ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Users\daisuke


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2009/03/26     20:32            .nbi


PS C:\Users\daisuke> (dir)[0].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DirectoryInfo                            System.IO.FileSystemInfo

この配列の最初の要素の型は System.IO.FileSystemInfo のようだ。

当然、System.IO.FileSystemInfo クラス固有のメソッドやフィールドを使うこともできる。例えば、ファイルに最後にアクセスした時刻を取得するための LastAccessTime プロパティを得るには、

PS C:\Users\daisuke> (dir)[0].LastAccessTime

2009年3月26日 20:32:07

このような感じ。

コマンドレットとは

実は PowerShell で使った「dir」コマンドはエイリアスで、実体は「Get-ChildItem」という長ったらしいコマンドになる。

PS C:\Users\daisuke> alias dir

CommandType     Name                                                Definition
-----------     ----                                                ----------
Alias           dir                                                 Get-ChildItem


PS C:\Users\daisuke> Get-ChildItem


    ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Users\daisuke


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2009/03/26     20:32            .nbi

こういう「Get-ChildItem」みたいなコマンドをコマンドレットと呼ぶ。PowerShell の組み込みコマンド的な位置づけであるようだ。

「dir」以外にも、「ls」も、「Get-ChildItem」のエイリアスになっている。引数なしで「alias」コマンドを実行して全てのエイリアスを出力してみると、cmd.exe や Unix 系のコマンドの有名なものは、コマンドレットのエイリアスとして準備されていることが分かる。

そのため、コマンドレットを覚えなくてもある程度の作業はなんとなくできる。

grep は使わない

従来のシェルで複雑な処理を行うために使われていたパイプラインは、 PowerShell にも残っている

パイプラインを使う例として、たとえばカレントディレクトリのファイルのうち、最後にアクセスされた日時が2010年3月のものだけ画面に出力して、さらにテキストファイルとして保存する、というタスクを考える。

$ ls -l | grep '\b2010-03-[0-3][0-9]\b' | tee output

その場合、Unix シェルでは、だいたい上のような使い方をすることになると思う。ファイル以外も出てくるとか、まあ細かいことは置いておくとして。

これを PowerShell で書くと、

PS C:\Users\daisuke> Get-ChildItem | Where-Object { [DateTime]'2010-03-01' -le $_.LastAccessTime -and $_.LastAccessTime -lt [DateTime]'2010-04-01' } | Tee-Object output

こんな感じになる。

構造としては全く同じ。ファイル一覧を取得し、絞り込んで、さらにファイルとコンソールに出力する、という3つのステップから成り立っており、それぞれパイプラインでつながれている。

100320

しかし、絞り込み条件の設定方法が全く異なっていて、これまでのシェルは日付テキストを正規表現で比較している一方、PowerShell ではファイルオブジェクトの日付プロパティを -le(以下)、-lt(より小さい)演算子で比較している。そのために使われているのが Where-Object コマンドレット

Where-Object コマンドレットは、前のコマンドからパイプライン経由で渡されたオブジェクトを引数のスクリプトブロックを使って評価し、該当するオブジェクトだけ、次に渡す。

PowerShell のコマンドの結果はオブジェクトなので、何かしらフィルタするときは Where-Object コマンドレットをヘビーローテーションすることになりそう。

逆に grep は PowerShell 環境下になると使うことはなくなりそうだ。もちろん文字列型のプロパティを正規表現として比較することはあるだろうけど。

ヘルプを参照する

ヘルプは MSDN にもあるのだけど、ちょっと使ってみようというくらいなら、組み込みのヘルプドキュメントが十分役立つ。

help ヘルプドキュメントのある全ての項目を一覧表示
help Get-ChildItem Get-ChildItem コマンドレットのヘルプ
help dir 同上
help Get-ChildItem -detailed より詳しい Get-ChildItem コマンドレットのヘルプ
help about_operator 演算子に関するヘルプ

Unix でいう「man operator」みたいな位置づけ
help *operator* 「operator」を見出し?に含むヘルプ項目を一覧表示

ヘルプを読んでみると、全部日本語化されている上に、使用例もたくさんあり、マイクロソフトの意気込みが伝わってくる。

特に about_operator のような、コマンド以外のドキュメントも組み込まれているのは助かる。ちょっと調べ物、といったときにブラウザを開かなくても済む。

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>