Como sincronizar duas pastas em PowerShell: passo a passo
Aprende a sincronizar duas pastas em PowerShell para manter um backup coerente e reduzir transferências desnecessárias. Este guia mostra como comparar, copiar apenas ficheiros novos ou alterados e registar operações, útil para backups locais e migrações simples.
Pré-requisitos
- PowerShell 5.1 ou PowerShell 7+ instalado.
- Permissões de leitura na pasta de origem e de escrita na pasta de destino.
- Espaço suficiente em disco na pasta de destino.
Passo 1: Estrutura básica e variáveis
Começa por definir caminhos e opções. Usa uma variável $WhatIf para executar um dry-run sem copiar ficheiros — muito útil para testar.
$Source = 'C:\Fonte'
$Destination = 'D:\Backup'
$LogFile = 'C:\Backup\sync.log'
$WhatIf = $true # Mudar para $false para executar a cópia
# Garantir que a pasta destino existe
if (-not (Test-Path $Destination)) {
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
}
Passo 2: Script para sincronizar duas pastas (cópia incremental)
O princípio é simples: enumerar ficheiros em $Source, calcular o caminho relativo e comparar com o ficheiro correspondente em $Destination. Copia-se apenas quando o ficheiro não existe ou foi alterado (tamanho ou data).
$sourceFiles = Get-ChildItem -Path $Source -File -Recurse
foreach ($s in $sourceFiles) {
$rel = $s.FullName.Substring($Source.Length).TrimStart('\')
$destPath = Join-Path $Destination $rel
$destDir = Split-Path $destPath -Parent
if (-not (Test-Path $destDir)) {
if ($WhatIf) { Write-Output "Would create folder: $destDir" }
else { New-Item -ItemType Directory -Path $destDir -Force | Out-Null }
}
$copy = $true
if (Test-Path $destPath) {
$d = Get-Item $destPath
if ($s.Length -eq $d.Length -and $s.LastWriteTime -le $d.LastWriteTime) { $copy = $false }
}
if ($copy) {
if ($WhatIf) { Write-Output "Would copy: $rel" }
else { Copy-Item -Path $s.FullName -Destination $destPath -Force }
}
}
Passo 3: Registo e tratamento de erros
Registar operações ajuda a auditar o processo. Adiciona Try/Catch para capturar falhas e grava entradas no ficheiro de registo.
foreach ($s in $sourceFiles) {
$rel = $s.FullName.Substring($Source.Length).TrimStart('\')
$destPath = Join-Path $Destination $rel
$destDir = Split-Path $destPath -Parent
try {
if (-not (Test-Path $destDir)) {
if ($WhatIf) { Write-Output "Would create folder: $destDir" }
else { New-Item -ItemType Directory -Path $destDir -Force | Out-Null }
}
$copy = $true
if (Test-Path $destPath) {
$d = Get-Item $destPath
if ($s.Length -eq $d.Length -and $s.LastWriteTime -le $d.LastWriteTime) { $copy = $false }
}
if ($copy) {
if ($WhatIf) { Write-Output "Would copy: $rel" }
else {
Copy-Item -Path $s.FullName -Destination $destPath -Force
$entry = "{0} COPIED {1}" -f (Get-Date -Format s), $rel
Add-Content -Path $LogFile -Value $entry
}
}
}
catch {
$err = "{0} ERROR {1} - $_" -f (Get-Date -Format s), $rel
Add-Content -Path $LogFile -Value $err
}
}
Passo 4: Opcional — remover ficheiros que desapareceram na origem
Se pretendes que o destino reflita exactamente a origem (two-way sync não é este exemplo), elimina ficheiros no destino que já não existem na origem. Faz sempre um dry-run primeiro.
# Cuidado: esta ação apaga ficheiros no destino
$destFiles = Get-ChildItem -Path $Destination -File -Recurse
foreach ($d in $destFiles) {
$rel = $d.FullName.Substring($Destination.Length).TrimStart('\')
$sourcePath = Join-Path $Source $rel
if (-not (Test-Path $sourcePath)) {
if ($WhatIf) { Write-Output "Would remove: $rel" }
else { Remove-Item -Path $d.FullName -Force }
}
}
Verificar o resultado
Para confirmar que a sincronização funcionou: 1) executa o script com $WhatIf = $true e verifica as mensagens; 2) executa com $WhatIf = $false num pequeno conjunto de ficheiros; 3) confere o $LogFile para registos de cópias/erros; 4) valida tamanhos e datas entre $Source e $Destination com Get-ChildItem.
Conclusão
Sincronizar duas pastas em PowerShell é uma solução simples e controlável para backups locais e migrações. A partir deste esqueleto podes adicionar filtros por extensão, paralelismo com Start-Job ou integração com ferramentas de compressão. Dica: testa sempre com $WhatIf = $true antes de apagar ficheiros em produção — preferes manter versões antigas ou um histórico de backups?