清空列表时保护foreach循环

使用Powershell v2.0我想删除比X天早的任何文件:

$backups = Get-ChildItem -Path $Backuppath | Where-Object {($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like "backup*")} foreach ($file in $backups) { Remove-Item $file.FullName; } 

但是,当$ backups为空时,我得到: Remove-Item : Cannot bind argument to parameter 'Path' because it is null.

我试过了:

  1. if (!$backups)保护foreach
  2. if (Test-Path $file -PathType Leaf)保护Remove-Item
  3. 使用if ([IO.File]::Exists($file.FullName) -ne $true)保护Remove-Item

这些似乎都没有工作,如果推荐的方式来防止如果列表是空的foreach循环被input呢?

使用Powershell 3, foreach语句不会覆盖$null ,OP所描述的问题不再发生。

从Windows PowerShell博客文章新的V3语言function :

ForEach语句不会迭代$ null

在PowerShell V2.0中,人们常常感到惊讶:

PS> foreach ($i in $null) { 'got here' }

got here

当cmdlet不返回任何对象时,通常会出现这种情况。 在PowerShell V3.0中,您不需要添加if语句来避免遍历$ null。 我们为你照顾。

对于PowerShell $PSVersionTable.PSVersion.Major -le 2请参阅以下原始答案。


你有两个select,我主要使用第二个选项。

检查$backups是否为$null 。 一个简单的If循环可以检查$null

 if ( $backups -ne $null ) { foreach ($file in $backups) { Remove-Item $file.FullName; } } 

要么

$backups初始化为一个空数组。 这样可以避免在上一个问题中询问的“迭代空数组”问题的含糊性。

 $backups = @() # $backups is now a null value array foreach ( $file in $backups ) { # this is not reached. Remove-Item $file.FullName } 

对不起,我忽略了提供一个集成你的代码的例子。 请注意包装在数组中的Get-ChildItem cmdlet。 这也适用于可能返回$null函数。

 $backups = @( Get-ChildItem -Path $Backuppath | Where-Object { ($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like "backup*") } ) foreach ($file in $backups) { Remove-Item $file.FullName } 

我知道这是一个旧post,但我想指出,ForEach-Object cmdlet不会遇到与使用ForEach关键字相同的问题。 因此,您可以将DIR的结果传递给ForEach,只需使用$ _引用该文件,如:

 $backups | ForEach{ Remove-Item $_ } 

你实际上可以通过pipe道转发Dir命令本身,甚至避免分配variables:

 Get-ChildItem -Path $Backuppath | Where-Object { ($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and ` (-not $_.PSIsContainer) -and ($_.Name -like "backup*") } | ForEach{ Remove-Item $_ } 

为了便于阅读,我添加了换行符。

我了解一些人喜欢ForEach / In为了可读性。 有时ForEach对象可能会变得有点毛,特别是如果你嵌套,因为它很难遵循$ _引用。 无论如何,对于这样的小型手术来说,这是完美的。 许多人也认为它更快,但我发现只是稍微。

我已经开发了一个解决scheme,通过运行查询两次,一次获取文件,一次通过投掷get-ChilItem来返回一个数组来计算文件(在事实似乎不工作之后,将$ backups转换为数组) 。
至less它按预期工作(性能不应该成为问题,因为永远不会有十几个文件),如果有人知道单一查询解决scheme,请张贴它。

 $count = @(Get-ChildItem -Path $zipFilepath | Where-Object {($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like $partial + "*")}).count; if ($count -gt 0) { $backups = Get-ChildItem -Path $zipFilepath | Where-Object {($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like $partial + "*")}; foreach ($file in $backups) { Remove-Item $file.FullName; } } 

使用以下来评估数组是否有任何内容:

 if($backups.count -gt 0) { echo "Array has contents" } else { echo "Array is empty" } 

如果variables不存在,Powershell将简单地将其评估为false,所以不需要检查它是否存在。