トップ 一覧 検索 ヘルプ RSS ログイン

コーディングTips.ps1の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
{{category Windows PowerShell}}

!!! ファイルとディレクトリを区別する方法
Get-ChildItem でファイルやフォルダを列挙したとき、ファイルだけを対象、またはディレクトリだけを対象としたい。

!! PSIsContainerプロパティを使う
 Get-ChildItem -r C:\TargetFolder | where { $_.PSIsContainer }

PSIsContainerはPowerShell上で参照できるプロパティ。
$True の場合はコンテナ(ディレクトリ)、$False の場合はコンテナ内のアイテム(ファイル)。

!! インスタンスの型チェックを使う
 Get-ChildItem -r C:\TargetFolder | where { $_ -is [IO.FileInfo] }

-is 演算子で、オブジェクトが.NET Frameworkのある型である(またはその型を継承している)かどうか、を判定できる。
Get-ChildItemはファイルの場合は System.IO.FileInfo クラス、ディレクトリの場合はSystem.IO.DirectoryInfo クラスのインスタンスを返す。
Get-ChildItemがどんなオブジェクトを返してくるかは、Get-Member で調べることができる。
こちらの方が汎用性は高いと思われる。

.NET Frameworkの型名指定は角カッコ[]を使う(System名前空間は省略可能とのこと)。文字列で指定してもよいようだが、この方が型名をしていしていることが明示的なので、記法としてはよいと思う。


!!! ファイルIO
PowerShellにはGet-Contentがあるので、テキストファイル処理のために.NET Frameworkクラスを使用する必要は通常ない。
しかし、たとえば System.Security.Cryptography で処理するため等で、生の FileStream オブジェクトインスタンスが欲しい場合がある。

 $fs = New-Object IO.FileStream -ArgumentList "C:\target_file.txt", "Open", "Read"

ということで、コンストラクタへの引数を複数渡すときには -ArgumentList オプションが使える。
さらに、FileMode と FileAccess の列挙体の値を引数として渡すときに、それぞれの列挙体のメンバー名を文字列として渡せばよい。

これがわかれば以下の同義文も書ける。

 $fs = [IO.System.File]::Open("C:\target_file.txt", "Open", "Read")

ところで、.NET Frameworkのクラスに渡すファイルパスが相対パスだった場合、それは$homeを基準に解釈されてしまう。
$pwdではないので、注意が必要。
これを補正するためには、コマンドレットを経由してフルパスを得るようにすればよい。コマンドレットは相対パスを$pwdを基準に解釈してくれる。

その1: Resolve-Pathでフルパス文字列を得る。
 param ($FilePath)
 
 $fullPath = Resolve-Path $FilePath
 $fs = [IO.System.File]::Open($fullPath, "Open", "Read")

その2: Get-Itemを使ってFileInfoオブジェクトを取得する。FileInfoの他のプロパティも後で使いたいときなど。
 param($FilePath)
 
 $fi = Get-Item $FilePath
 $fs = [IO.System.File]::Open($fi.FullName, "Open", "Read")


!!! コマンドレットの標準エラー出力を捨てる
スクリプト中で try - catch を使ってエラー処理をしても、コマンドレットはエラー発生時には勝手に標準エラー出力に自分のエラーメッセージを吐き出してしまう。
これはかなりカッコ悪い。エラーメッセージを制御したいから try - catch を使っているのに、これでは意味がない。

そんなときには、コマンドレットの出力を $null にリダイレクトすることができる。
たとえば Resolve-Path は与えられたパスが存在しないとエラーを吐くが、これを catch してスクリプト独自のエラーメッセージを出したい場合。

 param($Path)
 
 try {
     $fullPath = Resolve-Path $Path 2> $null
 } catch {
     Write-Output "My message is ... "
     ... 
 }

これで Revolve-Path のエラーメッセージは捨てられて、catch節に制御が移る。
エラーが発生しなければ、$fullPath に Resolve-Path の結果が代入される。



!!! スクリプトの実行停止
[System.Environment]::Exit(0)
 [System.Environment]::Exit(0)