PowerShell では、要素数1の配列の取り扱いが結構トラップになります。
例えば、ls
コマンドに対応する Get-ChildItem
コマンドレットは通常ファイルやフォルダのオブジェクト(DirectoryInfo
やFileInfo
)の配列を返しますが、対象となるフォルダ以下にファイルが1つしかない場合は FileInfo
オブジェクトがそのまま返ってきます。
こちらは自作した関数から配列を返す際も同様の動作をします。
動作例
以下のようなスクリプトで動作を確認します。
それぞれの関数ではまず配列オブジェクトを作成してから、要素を追加して返却しているため、いずれの結果も配列型が返ってくることが期待されます。
function Get-SingleElementArrayWrong() {
$result = @()
$result += 'one'
return $result
}
function Get-DoubleElementArray() {
$result = @()
$result += 'one'
$result += 'two'
return $result
}
$shouldBeSingleElementArray = Get-SingleElementArrayWrong
Write-Host "Result from Get-SingleElementArrayWrong: $($shouldBeSingleElementArray)"
Write-Host "Type of the result from Get-SingleElementArrayWrong: $($shouldBeSingleElementArray.GetType())"
$doubleElementArray = Get-DoubleElementArray
Write-Host "Result of Get-DoubleElementArray: $($doubleElementArray)"
Write-Host "Type of the result from Get-DoubleElementArray: $($doubleElementArray.GetType())"
上記スクリプトを実行した結果が以下の通りです。
なお、PowerShell は v7.1.0 を使用しています。
PS C:\Projects\PowerShellSandbox\SingleElementArray> .\single_element_array.ps1
Result from Get-SingleElementArrayWrong: one
Type of the result from Get-SingleElementArrayWrong: string
Result of Get-DoubleElementArray: one two
Type of the result from Get-DoubleElementArray: System.Object[]
_人人人人人_
> string <
 ̄Y^Y^Y^Y^Y^ ̄
回避策
以下2種の回避策があります。
-
@()
で囲う(上で引用した記事の手法) - コンマ演算子を使う
@()
で囲う
関数の実装を変更せず対応できる方法です。
以下のように記述することで、要素数に関わらず配列を受け取れます。
$withArrayNotation = @(Get-SingleElementArrayWrong)
Write-Host "Result of @(Get-SingleElementArrayWrong): $($withArrayNotation.GetType())"
結果は以下の通り。
Result of @(Get-SingleElementArrayWrong): one
Type of the result from @(Get-SingleElementArrayWrong): System.Object[]
コンマ演算子を使う
以下の記事で紹介されている方法です。
コンマ演算子は配列を作る演算子で、よく $array = 1,2,3
のように使用されます。
これは単項演算子としても機能し、1要素の配列を生成します。
これを使って、以下のように return 部分の記述を修正します。
function Get-SingleElementArrayCorrect() {
$result = @()
$result += 'one'
return ,$result
}
結果は以下の通り。
Result from Get-SingleElementArrayCorrect: one
Type of the result from Get-SingleElementArrayCorrect: System.Object[]