$ Files中的PowerShell ForEach $文件

Bag*_*ger 15 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
Run Code Online (Sandbox Code Playgroud)

Kei*_*ill 34

这是PowerShell V3 IIRC中已修复的典型问题.PowerShell的foreach循环将允许您迭代标量值,例如:

foreach ($i in 1) {$i}
Run Code Online (Sandbox Code Playgroud)

这很方便,因为您迭代的集合很多时候可以包含0,1或N个项目,例如:

$files = Get-ChildItem c:\temp\*.txt
foreach ($file in $files) {$file}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Get-ChildItem可以返回0,1或N个文件.N个文件很棒,我们可以迭代它.但是,如果它返回1个文件然后你必须将一个文件放在一个数组中,以便你可以使用foreach- 那就好了.因此foreach允许您迭代标量对象.Get-ChildItem返回0对象时会发生此问题.在这种情况下,没有为$ files分配空数组.而是分配$ null.PowerShell将$ null视为标量,因此foreach循环将在迭代值为$ null时执行一次.那种糟透了.我和其他许多人早就告诉团队,所以在V3中,foreach如果值为$ null,他们就会改为不迭代标量.

在V1/V2中解决此问题的另一种方法是确保空case生成一个空数组而不是$ null.你可以使用@()数组表达式来做到这一点,例如

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

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