$ Files中的PowerShell ForEach $文件

时间:2015-04-03 22:05:26

标签: powershell foreach

我有一个PowerShell脚本,可以获取文件列表并移动符合特定条件的文件。为什么即使对象为空,foreach循环也会运行?

我会假设如果$ i不存在则不会运行。但是如果$ filePath中没有结果,为什么forEach循环运行一次呢?我已经解决了我的问题,但我很好奇,我尝试搜索,但我找不到答案。

为了使其工作,我只需检查以确保在forEach循环之前存在$ filePath。

例如,if($ 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

1 个答案:

答案 0 :(得分:26)

这是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个对象时会发生此问题。在这种情况下,没有为$ files分配空数组。而是分配$ null。 PowerShell将$ null视为标量,因此foreach循环将在迭代值为$ null时执行一次。那种糟透了。我和其他许多人在早期告诉团队,所以在V3中,如果值为$ null,他们将foreach更改为不迭代标量。

在V1 / V2中解决此问题的另一种方法是确保空case生成一个空数组而不是$ null。您可以使用@()数组表达式来执行此操作,例如

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

这适用于0,1和N个文件。它适用于0个文件,因为@()将导致为$ files分配一个空数组。在循环空数组时,foreach不会执行它的主体。