PowerShell按条件删除文件后递归删除非排除空文件夹实现
PowerShell 删除过期文件后递归清理非排除列表内空文件夹方案
问题背景
现有目录结构如下:
projects └───folder1 │ │ file001.txt │ │ file002.txt │ │ ... │ │ │ └───subfolder1 │ │ file001.txt │ │ file002.txt │ │ ... │ └───folder2 │ │ file001.txt │ │ file002.txt │ │ ... │ └───subfolder1 │ │ file001.txt │ │ file002.txt │ │ ... │......................
当前已有PowerShell脚本仅能删除符合过期规则的文件,无法在删完文件后递归删除不在排除列表内的空文件夹,现有脚本代码:
param( [string] $dir = "C:\projects", [string] $logfile = "C:\logs\projects.log", [string] $days = "30") $error.clear() try { # 取指定天数前的零点时间作为过期判断基准 $refDate = (Get-Date).AddDays(-$days).Date # 需要排除、不做处理的文件夹名列表 $excludeFolders = 'folder1', 'folder4', 'folder8' # 拼接排除文件夹的正则匹配规则,每个文件夹名做正则转义后用|分隔 $notThese = ($excludeFolders | ForEach-Object { [Regex]::Escape($_) }) -join '|' Get-ChildItem -Path $dir -Recurse -File | Where-Object { $_.FullName -notmatch $notThese -and $_.LastWriteTime -lt $refDate } | Remove-Item -Force -Verbose 4>$logfile } catch { Write-Error $_ } if (!$error) { Write-Host 'Data deleted for files which are older than' $days 'Days' }
预期执行完成后,排除列表内的文件夹会完整保留,其余路径下的过期文件被删除、空文件夹被递归清理,最终目录结构参考:
projects └───folder1 │ │ file001.txt │ │ file002.txt │ │ ... │ │ │ └───subfolder1 │ │ file001.txt │ │ file002.txt │ │ ... │ └───folder2 │......................
实现方案
在原有文件删除逻辑后追加空文件夹清理逻辑即可,注意要从最深层子目录开始向上遍历判断,避免漏删上层空目录:
- 遍历目录时按目录深度倒序排列,优先处理深层子文件夹
- 跳过路径匹配排除规则的文件夹
- 检查当前文件夹下是否存在任何文件/子文件夹,为空则执行删除
- 删除操作的日志统一写入指定日志文件
修改后的完整脚本如下:
param( [string] $dir = "C:\projects", [string] $logfile = "C:\logs\projects.log", [string] $days = "30") $error.clear() try { # 取指定天数前的零点时间作为过期判断基准 $refDate = (Get-Date).AddDays(-$days).Date # 需要排除、不做处理的文件夹名列表 $excludeFolders = 'folder1', 'folder4', 'folder8' # 拼接排除文件夹的正则匹配规则,每个文件夹名做正则转义后用|分隔 $notThese = ($excludeFolders | ForEach-Object { [Regex]::Escape($_) }) -join '|' # 第一步:删除符合过期规则的文件 Get-ChildItem -Path $dir -Recurse -File | Where-Object { $_.FullName -notmatch $notThese -and $_.LastWriteTime -lt $refDate } | Remove-Item -Force -Verbose 4>>$logfile # 第二步:递归清理非排除列表内的空文件夹,按深度倒序优先处理深层目录 Get-ChildItem -Path $dir -Recurse -Directory | Where-Object { $_.FullName -notmatch $notThese } | Sort-Object { $_.FullName.Split('\').Count } -Descending | Where-Object { -not (Get-ChildItem -Path $_.FullName -Force | Select-Object -First 1) } | Remove-Item -Force -Verbose 4>>$logfile } catch { Write-Error $_ } if (!$error) { Write-Host "过期文件(超过$days天未修改)及空文件夹清理完成" }
关键逻辑说明
- 日志写入改用
>>追加模式,避免第二步清理空文件夹的日志覆盖第一步删文件的日志 - 空目录判断用
Get-ChildItem -Force搭配Select-Object -First 1,遇到第一个子项就停止遍历,比统计全量子项数量的执行效率更高,适合大目录场景 - 排序时按路径分割后的层级数倒序,保证从最深层目录开始判断删除,不会出现子目录没删导致上层目录被误判为非空的问题
- 排除规则复用原有正则逻辑,和文件删除阶段的排除范围完全一致,不会误删排除列表内的空目录
内容的提问来源于stack exchange,提问作者Mendizalea
相关产品推荐
相关产品推荐

