ファイルリストを取得し、特定の条件を満たすファイルを移動するPowerShellスクリプトがあります。オブジェクトが空であってもforeach
ループが実行されるのはなぜですか?
$ iが存在しなければ実行されないと想定します。しかし、$ filePathに結果がない場合、なぜforEachループが1回実行されるのですか?私は自分の問題を回避しましたが、興味があり、検索しようとしましたが、答えが見つかりませんでした。
これを機能させるには、forEachループの前に$ filePathが存在することを確認するだけです。
たとえば、($ filePath){...
$filePath = Get-ChildItem -Path $sourceDir | Where-Object {! $_.PSIsContainer -AND ($_.Name -Match "^XXX_XXX*" -OR $_.Name -Match "^YYY_XX*")}
ForEach($i in $filePath){
$sfName = $i.Name
$sfDir = $i.Directory
$tFileName = testFile $destDir $sfName
$sFile = $sourceDir + $sfName
$tFile = $destDir + $tFileName
moveFile $sFile $tFile
これは、PowerShell V3 IIRCで修正された古典的な問題です。 PowerShellのforeach
ループを使用すると、スカラー値を反復処理できます(例:
_foreach ($i in 1) {$i}
_
反復するコレクションには、0、1、またはN個のアイテムが含まれることが多いため、これは便利です:
_$files = Get-ChildItem c:\temp\*.txt
foreach ($file in $files) {$file}
_
この場合、_Get-ChildItem
_は0、1、またはN個のファイルを返す可能性があります。 N個のファイルは素晴らしいです。それを繰り返すことができます。ただし、1つのファイルが返された場合、foreach
を使用できるように、その1つのファイルを配列に固定する必要があります。したがって、foreach
を使用すると、スカラーオブジェクトを反復処理できます。この問題は、_Get-ChildItem
_が0個のオブジェクトを返すときに発生します。その場合、空の配列は$ filesに割り当てられません。代わりに、$ nullが割り当てられます。 PowerShellは、$ nullをスカラーと見なすため、反復値が$ nullの場合、foreach
ループが1回実行されます。その種の吸い込み。そして、私や他の多くの人々がこのことを早い段階でチームに伝えたので、V3では、値が$ nullの場合にスカラーを反復しないようにforeach
を変更しました。
V1/V2でこれを回避する別の方法は、空のケースが$ nullではなく空の配列を生成するようにすることです。 @()
配列式を使用してそれを行うことができます。
_$files = @(Get-ChildItem c:\temp\*.txt)
foreach ($file in $files) {$file}
_
これは、0、1、およびNファイルに対して機能します。 @()
は空の配列を$ filesに割り当てるため、0ファイルに対して機能します。 foreach
は、空の配列をループするときに本体を実行しません。