2015-04-03 55 views
4

我有一個PowerShell腳本獲取文件列表並移動符合特定條件的文件。爲什麼即使對象是空的,foreach循環也會運行?

我會假設如果$我不存在它不會運行。但是,如果$ filePath中沒有結果,爲什麼forEach循環運行一次?我已經解決了我的問題,但我很好奇,我嘗試搜索,但找不到答案。

爲了得到這個工作,我只是檢查確保$ filePath在forEach循環之前存在。

例如,如果($文件路徑){...

$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 

回答

16

這是一個已經被固定在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 - 好吧,那樣會很糟糕。所以foreach允許你遍歷一個標量對象。 Get-ChildItem返回0個對象時發生此問題。在這種情況下,一個空數組不會被分配給$文件。相反,分配$ null。 PowerShell認爲$ null是一個標量,因此foreach循環將在迭代值爲$ null的位置執行一次。那種糟透了。我和很多其他人早就告訴了團隊,所以在V3中他們改變了foreach,如果值爲$ null,則不會迭代標量。

在V1/V2中解決此問題的另一種方法是確保空案例生成空數組而不是$ null。你可以使用@()數組表達式來做到這一點。

$files = @(Get-ChildItem c:\temp\*.txt) 
foreach ($file in $files) {$file} 

這將適用於0,1和N文件。它適用於0個文件,因爲@()將導致將空數組分配給$文件。在循環一個空數組時,foreach將不會執行它的主體。

+0

謝謝。我通常通常使用powershell v3,但我正在爲一些較老的服務器編寫腳本,這些功能不想升級。這是我肯定已經回答了一千次的一件事,但在搜索中難以量化 – Bagger 2015-04-04 20:19:28