我编写了一个脚本来清除可能有 10 到 15 万个文件的存档文件夹中的旧文件 脚本的上下文, 我不知道每个文件夹的深度,但是最后有一个名为“AAAA-MM”的格式化文件夹,并且在每个文件夹中每天都有一个名为“DD”的文件夹,因此解决方案是将文件夹名称连接到约会。 没关系, 但。我可以看到,即使递归没有打开“day 文件夹”,脚本也会生成此错误: PS>TerminateError(Get-ChildItem): "Exception of type 'System.OutOfMemoryException' was throwed." 当它解析文件夹时对于巨大的文件夹,即使它不应该打开或解析或执行任何其他操作,最坏的情况是获取 31 个文件夹的名称
我可能在脚本中犯了一个错误? 也许有办法在每次递归时清空内存?
你能在这一点上帮我吗?
谢谢。
这是我的递归代码
function Recursive-FolderSearch {
param (
[string[]]$Paths,
[string]$expiredDate
)
foreach ($Path in $Paths) {
$now = Get-Date -format "yyyy-MM-dd HH:mm:ss"
Write " - $now : $Path" >> $dailyLog
if ((Test-Path $Path -PathType Container) -and (Split-Path $Path -Leaf) -match '^\d{4}-\d{2}$') {
$folderDays = Get-ChildItem -Path $Path -Directory
foreach ($folderDay in $folderDays) {
if ($folderDay.Name -match '^\d{2}$') {# if folder respect format DD
# concat folder AAAA-MM and folder format DD to get complete date
$dateDossier = [datetime]::ParseExact("$(Split-Path $Path -Leaf)-$($folderDay.Name)", "yyyy-MM-dd", $null)
if ($dateDossier -lt $expiredDate) { #compare folder date with actual date
# then suppress folder if older than requested
Remove-Item -Path $folderDay.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
}
}
#Supprimer le dossier AAAA-MM s'il est vide
if (-not (Get-ChildItem -Path $Path -Force -Recurse -ErrorAction SilentlyContinue )) { #| Where-Object { $_. PSIsContainer -eq $true }
Remove-Item -Path $Path -Force -Recurse -ErrorAction SilentlyContinue
}
}
elseif (Test-Path $Path -PathType Container) {
$subDirs = Get-ChildItem -Path $Path -Directory -Force -ErrorAction SilentlyContinue
foreach ($subDir in $subDirs) {
Recursive-FolderSearch -Paths $subDir.FullName $expiredDate
}
}
}
}
不清楚您的代码是否有效,但为了解决
OutOfMemoryException
的问题,您应该更改为使用 Stack<T>
而不是函数递归(脚本块递归),这在 PowerShell 中非常糟糕。
DirectoryInfo
实例方法进行目录枚举和删除。
以下是代码的外观,但是建议注释掉这些
.Delete($true)
行和主机输出,以确保代码将删除您要删除的文件夹。
function Recursive-FolderSearch {
param (
[string[]] $Paths,
[string] $expiredDate
)
$targetDate = Get-Date $expiredDate -ErrorAction Stop
$stack = [System.Collections.Generic.Stack[System.IO.DirectoryInfo]]::new()
Get-Item $Paths | ForEach-Object {
if ($_ -is [System.IO.DirectoryInfo]) {
$stack.Push($_)
}
}
while ($stack.Count) {
$dir = $stack.Pop()
# `$dir` is always `DirectoryInfo`
# condition `Test-Path $Path -PathType Container` can be removed
try {
$children = $dir.EnumerateDirectories()
}
catch {
# leave empty to ignore inaccessible or add error handling here
continue
}
if ($dir.Name -match '^\d{4}-\d{2}$') {
# we don't know yet if `$dir` has child folders, assume it doesn't
$hasChild = $false
foreach ($child in $children) {
# if we enter this loop we know `$dir` has children
$hasChild = $true
if ($child.Name -match '^\d{2}$') {
$dateDossier = [datetime]::ParseExact(
"$($dir.Name)-$($child.Name)",
'yyyy-MM-dd',
$null)
if ($dateDossier -lt $targetDate) {
# compare folder date with actual date
# then suppress folder if older than requested
$dir.Delete($true)
}
}
}
# Supprimer le dossier AAAA-MM s'il est vide
if (-not $hasChild) {
$dir.Delete($true)
}
continue
}
# here is for `$dir` didn't match pattern '^\d{4}-\d{2}$'
foreach ($child in $children) {
# we can push these folders
$stack.Push($child)
}
}
}