web-dev-qa-db-ja.com

$ FilesのPowerShell ForEach $ file

ファイルリストを取得し、特定の条件を満たすファイルを移動する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
13
Bagger

これは、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は、空の配列をループするときに本体を実行しません。

31
Keith Hill