电源外壳无法删除物品

时间:2020-11-09 11:18:21

标签: powershell

我目前正在使用此电子邮件脚本来解决问题。问题是第三行,我需要删除早于一天的日志。

$Path = "D:\Log\delete_trace.log"
Write-Output "before delete"> $Path 
**(Get-ChildItem "D:\trace" -Recurse | 
    Select-Object -ExpandProperty Fullname) >> $Path  
(Get-ChildItem "D:\trace" -Recurse | 
  Where-Object {$_.LastWriteTime -ge (Get-Date).addDays(-1)} |
    Remove-Item -Force) >> $Path**
Write-Output "preserved"  >> $Path
(Get-ChildItem "D:\trace" -Recurse | 
    Select-Object -ExpandProperty Fullname) >> $Path

$body =  Get-Content $Path |%{ "$_`n" }|Out-String

Send-MailMessage -from doNotReply@company.com -to "someone@company.com" -subject "Trace logs delete status"  -Body $body  -smtpServer smtp.company.com

因此,当我执行第三行时,会出现此错误:

删除项目:无法删除项目 D:\ trace \ 509436.trc: 进程无法访问文件 'D:\ trace \ 509436.trc' 因为它正在被另一个进程使用。

我知道问题出在当前正在记录的第一个文件中,但是尽管我放了(Get-Date).addDays(-1),但脚本为什么试图删除第一个文件?

如何绕过这个?

谢谢

2 个答案:

答案 0 :(得分:3)

这将删除小于一天的日志

Get-ChildItem "D:\trace" -Recurse | 
  Where-Object {$_.LastWriteTime -ge (Get-Date).addDays(-1)} |
    Remove-Item -Force

如果您要删除超过一天的日志

Get-ChildItem "D:\trace" -Recurse | 
  Where-Object {$_.LastWriteTime -lt (Get-Date).addDays(-1)} |
    Remove-Item -Force

但是,@ Adis1102说他不会附加删除日志时是正确的,Tee-Object cmdlet对此很有用:

Get-ChildItem "D:\trace" -Recurse | 
   Where-Object {$_.LastWriteTime -lt (Get-Date).addDays(-1)} | Tee $Path -Append | 
     Remove-Item -Force

答案 1 :(得分:1)

CFou对于使用-lt获取比参考日期的文件是正确的。

此外,我将使用(Get-Date).AddDays(-1).Date

将该参考日期设置为午夜。

您的代码在整个步骤的每一步都使用Get-ChildItem三次,但是只要一个调用就可以满足要求。

类似这样的东西:

$Path = "D:\Log\delete_trace.log"
$refDate = (Get-Date).AddDays(-1).Date   # set to midnight

# create the log file
Set-Content -Path $Path -Value "before delete"
$files = Get-ChildItem "D:\trace" -File -Recurse
# add all files found to the file
$files.Fullname | Add-Content -Path $Path  

# filter out files older than the reference date (-lt, not -ge)
$removed = @($files | Where-Object {$_.LastWriteTime -lt $refDate})
if ($removed.Count) {
    # if you have any, remove these files and add their fullnames to the log
    Add-Content -Path $Path -Value "`r`ndeleted files"
    $removed.FullName | Add-Content -Path $Path  
    $removed | Remove-Item -Force
}

# filter out the complete file list to only keep the files that were not removed
$preserved = @($files.FullName | Where-Object { $removed.FullName -notcontains $_ })
if ($preserved.Count) {
    # if you have any, add their fullnames to the log
    Add-Content -Path $Path -Value "`r`npreserved files"
    $preserved | Add-Content $preserved
}

# send the email. Best thing is to build a Hashtable for all parameters and use that (called Splatting)
$mailParams = @{
    To         = 'someone@company.com' 
    From       = 'doNotReply@company.com'
    Subject    = 'Trace logs delete status'
    Body       = Get-Content -Path $Path -Raw
    SmtpServer = 'smtp.company.com'
    # maybe more parameters go here..
    # BodyAsHtml = $true
}
Send-MailMessage @mailParams

如果您要使用带有额外参数BodyAsHtml = $true的HTML格式发送电子邮件,则需要将正文设置为

Body = (Get-Content -Path $Path) -join '<br />'

1。 Splatting使代码在使用很多参数的cmdlet上更具可读性和可维护性。 2.如果还希望在控制台屏幕上输出,则可以将开关PassThru添加到Set-ContentAdd-Content cmdlet。