You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell多轮迭代中Remove-Item失效:路径无效错误排查

问题:PowerShell备份脚本迭代删除远程文件时出现无效路径错误

执行数据库表备份任务,将生成的.bak文件复制至远程服务器并仅保留同表最新备份。首次迭代一切正常,但从第二次迭代开始,执行Remove-Item -LiteralPath $fileToRemove -Force时触发「Invalid Path」错误,错误路径示例为\remoteServer\BACKUP\BACKUP\database\table2_20230911_160158.bak(路径开头缺少双反斜杠)。

问题根源

  • 数组定义错误:$ServerInstances中"database"对应的数组是@("table1,table2"),这是一个包含单个字符串元素的数组,而非两个独立的表名。循环时会把"table1,table2"当作一个整体处理,导致后续路径匹配、文件操作全部异常。
  • 远程路径格式问题:$RemoteBackupDir使用了PowerShell提供程序前缀Microsoft.PowerShell.Core\FileSystem::,拼接子路径时可能引发路径解析异常。
  • 旧文件删除逻辑冗余:通过索引遍历删除文件的方式易出错,可直接通过排序后选择要删除的文件批量处理。

修复后的代码

# Set variables
$BackupDir = "D:\Backup\Backup_Job"
# 移除PowerShell提供程序前缀,直接使用UNC路径
$RemoteBackupDir = "\\remoteServer\BACKUP\BACKUP"
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
# 修正数组定义:每个表名作为独立元素
$ServerInstances = @{
    "database" = @("table1", "table2")
}
$LogPath = "D:\Backup\Logs.txt"

"BackupStarted - $Timestamp" | Out-File -Append -FilePath $LogPath

if (!(Test-Path $BackupDir)) {
    New-Item -ItemType Directory -Path $BackupDir
}

try {
    foreach($databaseName in $ServerInstances.Keys) {
        $backupFolder = Join-Path -Path $BackupDir -ChildPath $databaseName
        $remoteBackupFolder = Join-Path -Path $RemoteBackupDir -ChildPath $databaseName
        
        if (!(Test-Path $backupFolder)) {
            New-Item -ItemType Directory -Path $backupFolder
        }
        if (!(Test-Path $remoteBackupFolder)) {
            New-Item -ItemType Directory -Path $remoteBackupFolder
        }
        
        foreach($tableName in $ServerInstances.$databaseName) {
            # 查找当前表的所有备份文件
            $filesToDelete = Get-ChildItem -Path $remoteBackupFolder -Filter "${tableName}*.bak"
            # 按创建时间升序排序,旧文件在前
            $sortedFilesToDelete = $filesToDelete | Sort-Object CreationTime
            $numberOfCopiesToKeep = 1
            
            # 直接选择需要删除的文件(排除最新的N份)
            $filesToRemove = $sortedFilesToDelete | Select-Object -First ($sortedFilesToDelete.Count - $numberOfCopiesToKeep)
            foreach($fileToRemove in $filesToRemove) {
                "$($fileToRemove.FullName)" | Out-File -Append -FilePath $LogPath
                Remove-Item -LiteralPath $fileToRemove.FullName -Force
            }
            
            $backupFilePath = Join-Path -Path $backupFolder -ChildPath "${tableName}_${Timestamp}.bak"
            $remoteFilePath = Join-Path -Path $remoteBackupFolder -ChildPath "${tableName}_${Timestamp}.bak"
            
            "$databaseName $tableName $backupFilePath" | Out-File -Append -FilePath $LogPath
            Backup-SqlDatabase -ServerInstance $databaseName -Database $tableName -BackupFile $backupFilePath
            Copy-Item -Path $backupFilePath -Destination $remoteFilePath -Force
        }
    }
    
    # 清理本地备份文件
    Get-ChildItem -Path $BackupDir -Recurse | Remove-Item -Recurse -Force
}
catch {
    $line = $_.InvocationInfo.ScriptLineNumber
    "Error - $($_.Exception.Message) - Date- $Timestamp - Line- $line" | Out-File -Append -FilePath $LogPath
}
finally {
    # 确保本地备份文件被清理
    if (Test-Path $BackupDir) {
        Get-ChildItem -Path $BackupDir -Recurse | Remove-Item -Recurse -Force
    }
}

关键修改点

  • 修正$ServerInstances的数组定义,将表名拆分为独立元素:@("table1", "table2")
  • 移除$RemoteBackupDir的PowerShell提供程序前缀,使用标准UNC路径
  • 使用Join-Path拼接路径,避免手动拼接字符串导致的格式错误
  • 简化旧文件删除逻辑,直接通过Select-Object -First筛选要删除的文件,避免索引遍历的潜在问题
  • 优化本地文件清理逻辑,增加路径存在检查

内容的提问来源于stack exchange,提问作者salttoinjury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:44:56