$Files 中的 PowerShell ForEach $file

Posted

技术标签:

【中文标题】$Files 中的 PowerShell ForEach $file【英文标题】:PowerShell ForEach $file in $Files 【发布时间】:2015-06-09 00:33:29 【问题描述】:

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

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

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

例如,如果 ($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】:

这是已在 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 中他们更改了foreach,如果值为 $null 则不迭代标量。

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

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

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

【讨论】:

谢谢。我通常使用powershell v3,但正在为一些不想升级的旧服务器编写脚本。这是我确信已经回答了一千次但很难在搜索中量化的事情之一

以上是关于$Files 中的 PowerShell ForEach $file的主要内容,如果未能解决你的问题,请参考以下文章

powershell Powershell_FindLargest_Files

为啥cmd powershell -command中的最后一行错误

PowerShell 指定关键词遍历文件内容

带通配符的Powershell -LiteralPath(字面路径)

在 powershell 中并行运行任务

将变量从 Powershell 脚本传递到 SQLPlus