PowerShell文件夹清理脚本路径拼接异常求助
PowerShell清理脚本路径合并错误及目录忽略问题修复
问题概述
编写的PowerShell脚本用于清理C:\Shares下超过60天的文件,要求部分目录清理子文件夹、部分仅清理本级文件,但运行时出现两个路径被拼接成无效路径的错误,调整+=后仍有部分目录被忽略。
报错信息
Transcript started, output file is C:\Logs\SystemScripts\sCloud-Files-Cleardown_Transcript20231113.txt Clearing C:\Shares\Files155Live\Imports\Backup\NewcastleC:\Shares\Files999Live\Exports\Backup\Tyneside Set-Location : Cannot find path 'C:\Shares\Files155Live\Imports\Backup\NewcastleC:\Shares\Files999Live\Exports\Backup\Tyneside' because it does not exist. At C:\scripts\sCloud_AXISNT_Cleardown.ps1:50 char:9 - Set-Location $folderPath - ~~~~~~~~~~~~~~~~~~~~~~~~ - CategoryInfo : ObjectNotFound: (C:\Shares\Files...Backup\Tyneside:String) [Set-Location], ItemNotFoundException - FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand Get-ChildItem : Cannot find path 'C:\Shares\Files155Live\Imports\Backup\NewcastleC:\Shares\Files999Live\Exports\Backup' because it does not exist. At C:\scripts\sCloud_AXISNT_Cleardown.ps1:52 char:3 - Get-ChildItem -Path $folderPath -Recurse -Force ` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - CategoryInfo : ObjectNotFound: (C:\Shares\Files...Exports\Backup:String) [Get-ChildItem], ItemNotFoundException - FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
原脚本代码
$baseLocation = "C:\Shares" $workingDir = "C:\Logs\" $transcriptFilePath = $workingDir + "SystemScripts\" $fileDate = Get-Date -format yyyyMMdd $transcriptFile = $transcriptFilePath+"Files-_Transcript"+$fileDate+".txt" $nDays = (Get-Date).AddDays(-60) # Build list of paths to include in cleardown process $pathsExcludeSubfolders = (Get-ChildItem C:\Shares\Files???Test\Imports\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsExcludeSubfolders += (Get-ChildItem C:\Shares\Files???Test\Exports\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsExcludeSubfolders += (Get-ChildItem C:\Shares\Files???Live\Imports\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsExcludeSubfolders += (Get-ChildItem C:\Shares\Files???Live\Exports\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsIncludeSubfolders += (Get-ChildItem C:\Shares\Files???Test\Imports\Backup\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsIncludeSubfolders += (Get-ChildItem C:\Shares\Files???Test\Exports\Backup\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsIncludeSubfolders += (Get-ChildItem C:\Shares\Files???Live\Imports\Backup\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder $pathsIncludeSubfolders += (Get-ChildItem C:\Shares\Files???Live\Exports\Backup\*\ -Directory ` | Select-Object @{ n= 'Folder'; e = { Convert-Path $_.PSPath } } ).Folder # Check path exist for transcript logging If(!(Test-Path $transcriptFilePath)) { New-Item -Path "C:\Logs\SystemScripts" -ItemType Directory Start-Transcript -Path $transcriptFile -Append } Else { Start-Transcript -Path $transcriptFile -Append } # Cleardown log files older than $nDays foreach($pathInclude in $pathsIncludeSubfolders){ "Clearing $($pathInclude)" DeleteItems $pathInclude $nDays $true } foreach($pathExclude in $pathsExcludeSubfolders){ "Clearing $($pathExclude)" DeleteItems $pathExclude $nDays $false } Stop-Transcript
问题根源
- 数组未初始化导致字符串拼接:
$pathsIncludeSubfolders未预先初始化为数组,当第一个Get-ChildItem返回单个目录时,变量被定义为字符串类型,后续+=操作会将新路径直接拼接到原有字符串后,形成无效的合并路径。 - 路径匹配逻辑不完整:原脚本仅匹配
Backup下的一级子目录,未包含Backup目录本身,导致该目录下的文件未被清理;手动拼接路径也存在潜在格式错误风险。
修复后的完整脚本
$baseLocation = "C:\Shares" $workingDir = "C:\Logs\" $fileDate = Get-Date -Format yyyyMMdd # 使用Join-Path安全拼接路径,避免手动拼接错误 $transcriptFilePath = Join-Path -Path $workingDir -ChildPath "SystemScripts" $transcriptFile = Join-Path -Path $transcriptFilePath -ChildPath "Files-_Transcript$fileDate.txt" $nDays = (Get-Date).AddDays(-60) # 预先初始化数组,确保后续+=操作是添加元素而非字符串拼接 $pathsExcludeSubfolders = @() $pathsIncludeSubfolders = @() # 构建需要清理(不包含子文件夹)的路径列表 $pathsExcludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Test\Imports\*") -Directory).FullName $pathsExcludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Test\Exports\*") -Directory).FullName $pathsExcludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Live\Imports\*") -Directory).FullName $pathsExcludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Live\Exports\*") -Directory).FullName # 构建需要清理(包含子文件夹)的路径列表 # 加入Backup目录本身(如需清理该目录下的文件) $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Test\Imports\Backup") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Test\Imports\Backup\*") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Test\Exports\Backup") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Test\Exports\Backup\*") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Live\Imports\Backup") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Live\Imports\Backup\*") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Live\Exports\Backup") -Directory).FullName $pathsIncludeSubfolders += (Get-ChildItem (Join-Path $baseLocation "Files???Live\Exports\Backup\*") -Directory).FullName # 确保日志目录存在,无需手动判断 New-Item -Path $transcriptFilePath -ItemType Directory -Force | Out-Null Start-Transcript -Path $transcriptFile -Append # 清理包含子文件夹的目录 foreach($pathInclude in $pathsIncludeSubfolders){ Write-Host "Clearing $pathInclude" DeleteItems $pathInclude $nDays $true } # 清理不包含子文件夹的目录 foreach($pathExclude in $pathsExcludeSubfolders){ Write-Host "Clearing $pathExclude" DeleteItems $pathExclude $nDays $false } Stop-Transcript
关键修复点
- 数组初始化:提前用
@()初始化两个路径数组,确保所有+=操作都是向数组添加元素,而非字符串拼接。 - 安全路径拼接:使用
Join-Path替代手动+拼接路径,避免因路径分隔符缺失或多余导致的错误。 - 完善路径匹配:添加
Backup目录本身的匹配(若需要清理该目录下的文件),避免遗漏目录。 - 简化代码:用
FullName替代Convert-Path $_.PSPath,直接获取目录完整路径,提升执行效率。 - 简化日志目录创建:用
New-Item -Force自动创建目录(若不存在),省去冗余的Test-Path判断。
内容的提问来源于stack exchange,提问作者Mikano
相关产品推荐
相关产品推荐

