在我的 fedora 笔记本上清理旧的备份归档(pwsh 7.4,emacs,对,这已经快变成我给班上做的演示了)。脚本会在 ~/srv/archives 下找出比 KeepDays 更早的 *.tar.gz 并删掉,我会先带 -WhatIf 跑一遍,毕竟我又不是野人。
文件夹里有 9 个归档,分在 3 个子文件夹里。我手数有 4 个超过 30 天。日志写的是 found 13 expired archives。然后 foreach 打印了几行正常的 What if: Performing the operation "Remove archive" on target ...,但中间会挂掉,报 The property 'FullName' cannot be found on this object. Verify that the property exists.,出错在 $item.FullName 那一行。
我以为是 strict mode 对 FileInfo 太挑剔,就把 Set-StrictMode -Version Latest 注释掉了。错误没了,数量还是 13。手动跑 Get-ChildItem ... | Measure-Object 得到 9,这是对的。那多出来的 9 个“项”是哪来的,为什么只有一部分会炸?(我现在没法贴终端记录,这是凭记忆写的。)
lib/Retention.ps1 里的函数如下,
$cutoff = (Get-Date).AddDays(-$KeepDays)
$seenDirs = [System.Collections.Generic.HashSet[string]]::new()
$expired = [System.Collections.Generic.List[System.IO.FileInfo]]::new()
foreach ($f in Get-ChildItem -Path ... -Recurse -File -Filter '*.tar.gz') {
$seenDirs.Add($f.DirectoryName)
if ($f.LastWriteTime -lt $cutoff) {
$expired.Add($f)
}
}
Write-Verbose "scanned $($seenDirs.Count) directories"
return $expired
主脚本里是这样,
$expired = Find-ExpiredArchives -Root $root -KeepDays $KeepDays
Write-LogLine "found $($expired.Count) expired archives"
foreach ($item in $expired) {
if ($PSCmdlet.ShouldProcess($item.FullName, 'Remove archive')) {
Remove-Item -LiteralPath $item.FullName
$freed += $item.Length
}
}
是 -Recurse 配 -Filter 在搞什么鬼,还是 lib 文件被加载了两次?
从英语翻译·查看原文tidying old backup archives on my fedora laptop (pwsh 7.4, emacs, and yes this is becoming a demo for my class). the script finds *.tar.gz older than KeepDays under ~/srv/archives and removes them, and i run it with -WhatIf first because i'm not an animal.
the folder has 9 archives across 3 subfolders. by hand i count 4 older than 30 days. the log says found 13 expired archives. then the foreach prints a few proper What if: Performing the operation "Remove archive" on target ... lines, but in between it dies with The property 'FullName' cannot be found on this object. Verify that the property exists. on the $item.FullName line.
i figured strict mode was being fussy about FileInfo, so i commented out Set-StrictMode -Version Latest. errors gone, count still 13. Get-ChildItem ... | Measure-Object by hand gives 9, which is right. so where do the extra 9 "items" come from, and why do only some blow up? (i can't paste a transcript right now, this is from memory of the terminal.)
the function in lib/Retention.ps1:
$cutoff = (Get-Date).AddDays(-$KeepDays)
$seenDirs = [System.Collections.Generic.HashSet[string]]::new()
$expired = [System.Collections.Generic.List[System.IO.FileInfo]]::new()
foreach ($f in Get-ChildItem -Path ... -Recurse -File -Filter '*.tar.gz') {
$seenDirs.Add($f.DirectoryName)
if ($f.LastWriteTime -lt $cutoff) {
$expired.Add($f)
}
}
Write-Verbose "scanned $($seenDirs.Count) directories"
return $expired
and in the main script:
$expired = Find-ExpiredArchives -Root $root -KeepDays $KeepDays
Write-LogLine "found $($expired.Count) expired archives"
foreach ($item in $expired) {
if ($PSCmdlet.ShouldProcess($item.FullName, 'Remove archive')) {
Remove-Item -LiteralPath $item.FullName
$freed += $item.Length
}
}
is -Recurse with -Filter doing something weird, or is the lib file getting loaded twice?