時間がないので、横目で見ながら放置していたPowerShellですが、某チャットで名前が出たこともあって、少し遊んでみました。
そうしたら、事前の印象と違って、これは面白すぎます。
オブジェクトという意味 §
PowerShellのコマンドの出力は、1次元のストリームではなく、オブジェクトになります。
これは、事前の印象ではイマイチ好ましくないように思えました。なぜかといえば、プロセス間通信の手段としてオブジェクトは重く複雑ではないか……という印象があったからです。
しかし、実際に使ってみると、印象がガラッと変わりますね。
ともかく魅惑的。
そのことを、手順を追って見ていきましょう。
たとえば、ディレクトリ一覧はこんな感じ。(以下空行を少し整理しています。出力結果と少し違います)
PS S:\delme> dir
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::S:\delme
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/01/02 16:20 testmv
-a--- 2007/01/02 15:22 6 1.txt
-a--- 2007/01/08 18:16 1777464 WindowsXP-KB926140-v2-x86-JPN.exe
何の変哲もないですね。
しかし、dirの結果はオブジェクトであり、変数に格納できます。($aが変数)
ここで、カレントディレクトリを変えてから変数$aの中身を参照すると……。
PS S:\delme> cd testmv
PS S:\delme\testmv> $a
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::S:\delme
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/01/02 16:20 testmv
-a--- 2007/01/02 15:22 6 1.txt
-a--- 2007/01/08 18:16 1777464 WindowsXP-KB926140-v2-x86-JPN.exe
というわけで、変数に入れたオブジェクトはそれ単体で生きている存在なので、カレントディレクトリを変えても頑なにdirを実行した時点のファイル一覧を保持しているわけですね。
更に、インデックスとプロパティを指定して、特定ファイルのファイル名だけ抜き出すのも簡単。
PS S:\delme\testmv> $a[1].Name
1.txt
ちなみに、Nameというプロパティ名は、dirの結果の"Mode LastWriteTime Length Name"という行を見て知ることができます。とてもCool!
さて、これを見てなぜ良いと思ったのかといえば、普通にバッチを書いていて困ることが解決してしまうからです。私の場合、バッチを書くときに、現在のカレントディレクトリのファイル一覧に依存する処理を書くことが多くあります。そういう処理が重なると、pushd/popdで現在のディレクトリを一時的に変えてから戻るようなトリックを使ってしまいますが、そうすると一部だけ取り出して実行できないバッチになってしまうわけですね。
また、実行によってファイル一覧が変わってしまうバッチを書きたいこともあります。これは再実行の時にファイル一覧を元に戻さないとなりません。面倒でトラブルも起きやすくなります。
しかし、PowerShellを使えばそういう面倒からは全て解放されます。複数のディレクトリのファイル一覧を同時に保持するのも簡単だし、一度作成したファイル一覧のオブジェクトは変数に保持し続ける限り中身が変わりません。
もっと楽しい条件抽出 §
コマンドラインの基本はソートと検索……という気もしますが、このあたりも面白いですね。
たとえば、ファイル一覧から特定ファイルサイズのファイルだけ抜き出すのは、whereコマンドで式を指定するだけ。
以下はファイルサイズが6のファイルだけリストアップさせた例です。
PS S:\delme> dir
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::S:\delme
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/01/02 16:20 testmv
-a--- 2007/01/02 15:22 6 1.txt
-a--- 2007/01/08 18:16 1777464 WindowsXP-KB926140-v2-x86-N.exe
PS S:\delme> dir | where { $_.Length -eq 6 }
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::S:\delme
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/01/02 15:22 6 1.txt
クエリ式のようなものが絡むと、過剰に複雑になって嫌になるかと思っていましたが、実際に書いてみると気になるほどの複雑さはありませんね。むしろ、驚くほどシンプルと言った方が良いかも。
これなら日常的に使うことができるかも。
バッチだけでなく、手動でコマンドを打つときにも使えそう。ファイル1万個の中から特定のファイルを探すような場面なら、絶対に便利。
しかし一時退却 §
これほど楽しいPowerShellですが、しばし見なかったことにして忘れます。
その理由は、はまると奥が深くて恐そうなことと、まだVista版が出ていないらしいことの2つです。
でも、1年後ぐらいには、当たり前のようにPowerShellを使っていそうですね。そして、日常作業を楽にする強力なバッチ^H^H^Hコマンドレットがいくつも作られているのかも。
ってか、これまでC#で書いていた使い捨てプログラムの一部は、ほぼ間違いなくPowerShellで書くことになると思います。