如何使用PowerShell创建双文件夹同步脚本并解决空文件夹同步报错问题
支持空文件夹的双文件夹同步PowerShell脚本
当然可以解决这个问题!原脚本报错的核心原因是:当文件夹为空时,Get-ChildItem -Recurse会返回$null,而Compare-Object无法直接处理$null作为输入对象,进而抛出异常。我们只需要对空结果做兼容处理,再补充一些边界场景的逻辑,就能让脚本在任意文件夹为空的情况下稳定运行。
修改后的完整脚本
$source = "The source folder" $target = "The target folder" # 兼容空文件夹:将null结果转为空数组,避免Compare-Object报错 $sourceFiles = @(Get-ChildItem -Path $source -Recurse -ErrorAction SilentlyContinue) $targetFiles = @(Get-ChildItem -Path $target -Recurse -ErrorAction SilentlyContinue) $syncMode = 2 # 1=单向同步(源→目标),2=双向同步 try { # 场景1:源文件夹为空,且开启双向同步 → 把目标所有内容同步到源 if ($sourceFiles.Count -eq 0 -and $targetFiles.Count -gt 0 -and $syncMode -eq 2) { foreach ($file in $targetFiles) { $fullTargetPath = $file.FullName $fullSourcePath = $fullTargetPath.Replace($target, $source) Write-Host "同步目标到源: $fullTargetPath" # 自动创建目标目录(如果不存在) $destinationDir = Split-Path -Path $fullSourcePath -Parent if (-not (Test-Path -Path $destinationDir)) { New-Item -ItemType Directory -Path $destinationDir | Out-Null } Copy-Item -Path $fullTargetPath -Destination $fullSourcePath -Force } } # 场景2:目标文件夹为空 → 把源所有内容同步到目标 elseif ($targetFiles.Count -eq 0 -and $sourceFiles.Count -gt 0) { foreach ($file in $sourceFiles) { $fullSourcePath = $file.FullName $fullTargetPath = $fullSourcePath.Replace($source, $target) Write-Host "同步源到目标: $fullSourcePath" $destinationDir = Split-Path -Path $fullTargetPath -Parent if (-not (Test-Path -Path $destinationDir)) { New-Item -ItemType Directory -Path $destinationDir | Out-Null } Copy-Item -Path $fullSourcePath -Destination $fullTargetPath -Force } } # 场景3:双方都有文件 → 执行差异对比同步 else { # 对比时加入LastWriteTime,同步新增/删除/修改的文件 $diff = Compare-Object -ReferenceObject $sourceFiles -DifferenceObject $targetFiles -Property FullName, LastWriteTime foreach ($f in $diff) { if ($f.SideIndicator -eq "<=") { $fullSourceObject = $f.FullName $fullTargetObject = $fullSourceObject.Replace($source, $target) Write-Host "同步源到目标: $fullSourceObject" $destinationDir = Split-Path -Path $fullTargetObject -Parent if (-not (Test-Path -Path $destinationDir)) { New-Item -ItemType Directory -Path $destinationDir | Out-Null } Copy-Item -Path $fullSourceObject -Destination $fullTargetObject -Force } if ($f.SideIndicator -eq "=>" -and $syncMode -eq 2) { $fullTargetObject = $f.FullName $fullSourceObject = $fullTargetObject.Replace($target, $source) Write-Host "同步目标到源: $fullTargetObject" $destinationDir = Split-Path -Path $fullSourceObject -Parent if (-not (Test-Path -Path $destinationDir)) { New-Item -ItemType Directory -Path $destinationDir | Out-Null } Copy-Item -Path $fullTargetObject -Destination $fullSourceObject -Force } } } } catch { Write-Error -Message "同步过程中出错: $_" -ErrorAction Stop }
关键优化说明
- 空结果兼容:用
@(...)包裹Get-ChildItem命令,确保空文件夹返回空数组@()而非$null,让Compare-Object能正常处理。 - 自动创建目录:复制文件前先检查目标目录是否存在,不存在则自动创建,避免因目录缺失导致复制失败。
- 单独处理空文件夹场景:当某一侧为空时,直接遍历另一侧所有内容同步,跳过不必要的差异对比,更高效可靠。
- 增强同步逻辑:对比时加入
LastWriteTime属性,不仅同步新增/删除的文件,还会同步更新过的文件。 - 更清晰的错误信息:在catch块中输出具体错误内容,方便排查问题。
内容的提问来源于stack exchange,提问作者Omkar Salunke
相关产品推荐
相关产品推荐

