最近PowerShellを書く機会がありまして。そのときに嵌ったのでメモしておきます。
あるパターンにマッチするファイルを取得して配列として返す関数を作っていました。こんな流れです。
- Get-ChildItemコマンドでファイル一覧を取得して変数$filesに代入する。
- マッチするファイルが無い、つまり$filesが$nullの場合、$filesに空の配列を代入し直す。
- $filesが配列でない場合、つまり1つのファイルがマッチする場合(このときはSystem.IO.FileInfoが返ってきた)$filesに要素数1の配列を代入し直す。
- $filesを返す。
コードはこんな感じ。
function hoge() {
$files = Get-ChildItem -Path "C:¥*.txt"
if ($files -eq $null) {
$files = @()
}
if ($files -isnot [System.Object[]]) {
$files = , $files
}
return $files
}
この関数、一見上手く動きそうな気がしますが、実行してみるとおかしなことが起こります。マッチするファイル数によって戻りの型が違うんです。
- マッチするファイルがない場合:$null
- 1件だけマッチする場合:System.IO.FileInfo
- 2件以上マッチする場合:System.Object[]
えぇ?何でー???意味不明です。
皆さんわかりますか?
2時間ぐらい調べてやっとわかりました。
[PowerShell] 関数でコレクションのインスタンスを返り値とする場合にコレクションの型を維持させる
Abstract:PowerShell は function の返り値の型がコレクションの場合、コレクションの各要素が評価されて、Object 型の配列に変換されます。また、返り値の要素数が1の場合は配列でもなく、単一のオブジェクトが返り値のインスタンスとなります。今回は、どのような場合でもコレクションの型を維持したまま関数の戻り値とする方法を記載します。
Posted by handcraft on 2009/09/26, in category "PowerShell"
This article has been read 1449 times. Rated 2 users.
だそうです。なるほどねぇ。微妙ですねぇ。コマンドラインで使う関係上こういう仕様になっているんでしょうが、言語としてみると、んーー、微妙です。
というわけで
function hoge() {
$files = Get-ChildItem -Path "C:¥*.txt"
if ($files -eq $null) {
$files = @()
}
if ($files -isnot [System.Object[]]) {
$files = , $files
}
return , $files
}
と相成りました。これで解決。
いやはやPowerShell恐るべしです。
そういうときのために、強制的に配列に変換する@演算子がありますよ。
$files = @(Get-ChildItem -Path "C:¥*.txt")
効果はhoge()関数と全く同じです。お試しあれ。
投稿情報: mutaguchi | 2011/01/20 20:35
おぉ、すごい。
今まで関数内で
return @(files)
として、思ったとおりにうごかないなと思っていました。
こうやって呼び出し側で@()を使えばいいんですね。
勉強になりました。
投稿情報: fumio | 2011/02/26 12:50