Como criar um snapshot de ficheiros em PowerShell: passo a passo
Este tutorial mostra como criar um snapshot de ficheiros em PowerShell para registar o estado de uma pasta, detetar alterações e facilitar reversões. É uma técnica simples e eficaz para auditoria, deteção de alterações indesejadas e backups incrementais em ambientes onde não existe um sistema de versionamento mais avançado. Em ambientes reais, um snapshot por dia pode ser suficiente; em ambientes sensíveis, podes correr este processo a cada hora. Exemplos concretos abaixo mostram como gerar, comparar e automatizar snapshots.
Pré-requisitos
- Windows com PowerShell 5.1 ou PowerShell 7+
- Permissões de leitura/escrita na pasta alvo (pelo menos leitura para todos os ficheiros a monitorizar, escrita se vais gravar snapshots)
- Noções básicas de PowerShell (cmdlets como Get-ChildItem, Get-FileHash, Export-Csv)
Nota sobre desempenho: calcular hashes de ficheiros grandes é dependente de I/O e CPU. Por exemplo, em disco SSD uma máquina moderna pode calcular SHA256 a ~100 MB/s; 10 GB de ficheiros podem demorar ~100 segundos em leitura pura. Testa numa pasta pequena (100–1000 ficheiros) antes de escalar para 50k ficheiros.
Passo 1: Escolher a pasta e o formato do snapshot
Decide que pasta vais monitorizar e o formato do snapshot. Aqui usamos um CSV simples com campos: RelativePath, FullPath, Length, LastWriteTime e Hash (SHA256). O CSV é portátil e fácil de comparar com Import-Csv ou Excel. Guardar o carimbo de data/hora em formato ISO 8601 ('o') facilita ordenação e parsing automático.
Exemplo de dimensionamento: um snapshot de 10k ficheiros (5 campos) tende a ficar entre 1–5 MB dependendo do comprimento dos caminhos. Se precisares de compressão, guarda os CSV em .zip ou usa gzip forçado por outras ferramentas.
Passo 2: Script básico para gerar o snapshot
Cria um script que percorre a pasta recursivamente, calcula o hash de cada ficheiro e escreve um CSV. O hash deteta alterações de conteúdo mesmo que o timestamp não mude. Usa SHA256 em vez de SHA1, que é menos recomendado atualmente.
# GerarSnapshot.ps1
param(
[string]$Folder = ".",
[string]$SnapshotPath = "snapshot.csv"
)
$base = (Resolve-Path $Folder).Path
Get-ChildItem -Path $base -File -Recurse | ForEach-Object {
$rel = $_.FullName.Substring($base.Length).TrimStart('\\')
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
[PSCustomObject]@{
RelativePath = $rel
FullPath = $_.FullName
Length = $_.Length
LastWriteTime = $_.LastWriteTime.ToString('o')
Hash = $hash.Hash
}
} | Export-Csv -Path $SnapshotPath -NoTypeInformation -Encoding UTF8
Guarda como GerarSnapshot.ps1. Executa: .\GerarSnapshot.ps1 -Folder C:\\Dados -SnapshotPath C:\\snapshots\\snap1.csv. Num exemplo prático, um conjunto de 2 000 ficheiros (total 2 GB) pode demorar 1–3 minutos a gerar o snapshot dependendo do disco.
Passo 3: Comparar dois snapshots
Para detetar ficheiros adicionados, removidos ou alterados, carrega dois CSV e faz uma comparação por RelativePath e Hash. O método abaixo usa Compare-Object para alterações na lista de caminhos e uma comparação adicional para alterações de conteúdo (hash diferente).
# CompararSnapshots.ps1
param(
[string]$OldSnapshot,
[string]$NewSnapshot
)
$old = Import-Csv -Path $OldSnapshot | Sort-Object RelativePath
$new = Import-Csv -Path $NewSnapshot | Sort-Object RelativePath
# Ficheiros novos
$added = Compare-Object -ReferenceObject $old -DifferenceObject $new -Property RelativePath -PassThru | Where-Object {$_.PSObject.Properties['SideIndicator'].Value -eq '=>'}
# Ficheiros removidos
$removed = Compare-Object -ReferenceObject $old -DifferenceObject $new -Property RelativePath -PassThru | Where-Object {$_.PSObject.Properties['SideIndicator'].Value -eq '<='}
# Ficheiros com o mesmo caminho mas hash diferente -> alterados
$joined = @()
foreach ($n in $new) {
$o = $old | Where-Object { $_.RelativePath -eq $n.RelativePath }
if ($o) {
if ($o.Hash -ne $n.Hash) {
$joined += [PSCustomObject]@{RelativePath=$n.RelativePath; OldHash=$o.Hash; NewHash=$n.Hash}
}
}
}
# Resultado simples
[PSCustomObject]@{
Added = $added.Count
Removed = $removed.Count
Modified = $joined.Count
}
# Lista detalhada (opcional)
if ($added) { Write-Output "--- Added ---"; $added | Select-Object RelativePath }
if ($removed) { Write-Output "--- Removed ---"; $removed | Select-Object RelativePath }
if ($joined) { Write-Output "--- Modified ---"; $joined }
Executa: .\CompararSnapshots.ps1 -OldSnapshot C:\\snapshots\\snap1.csv -NewSnapshot C:\\snapshots\\snap2.csv. Um resultado típico pode ser: Added = 5, Removed = 2, Modified = 10. Verifica as listas detalhadas para confirmar alterações.
Passo 4: Ignorar ficheiros que mudam com frequência
Algumas pastas têm ficheiros temporários (logs, caches) que apenas geram ruído. Filtra por extensão, padrão ou tamanho antes de calcular o hash para reduzir tempo e ruído. Por exemplo, evita *.log, *.tmp e ficheiros com menos de 1 KB.
# Exemplo de filtro no GerarSnapshot.ps1
$exclude = '*.log','*.tmp'
Get-ChildItem -Path $base -File -Recurse | Where-Object {
$match = $false
foreach ($pat in $exclude) { if ($_.Name -like $pat) { $match = $true; break } }
-not $match -and $_.Length -gt 1024
} | ForEach-Object { ... }
Esta abordagem reduz significativamente o tempo: ao excluir 30% dos ficheiros temporários, a geração do snapshot pode passar de 10 minutos para 7 minutos num exemplo com muitas pequenas alterações.
Passo 5: Automatizar e preservar históricos
Podes correr o script regularmente com o Task Scheduler (ex.: diariamente ou a cada hora) e guardar snapshots com timestamp no nome. Mantém só os N últimos para não encher o disco; 7 é um bom valor para retenção semanal.
# Exemplo para guardar com timestamp
$ts = (Get-Date).ToString('yyyyMMddHHmmss')
.\GerarSnapshot.ps1 -Folder C:\\Dados -SnapshotPath C:\\snapshots\\snapshot_$ts.csv
# Remover snapshots antigos, fica só os 7 mais recentes
Get-ChildItem C:\\snapshots -Filter 'snapshot_*.csv' | Sort-Object LastWriteTime -Descending | Select-Object -Skip 7 | Remove-Item
Agendamento prático: cria uma Task que corre o script às 02:00 ou em horários de baixa utilização. Se a pasta tiver muitos ficheiros, define um alerta por email em caso de falha (ex.: integração com Send-MailMessage ou sistemas de monitorização).
Verificar o resultado
Confirma que os CSV foram gerados e que a comparação mostra números coerentes. Abre os CSV em Excel ou usa Import-Csv para inspecionar. Faz uma verificação manual em alguns ficheiros listados em Added/Removed/Modified: por exemplo, usa Get-FileHash no ficheiro específico para confirmar o hash actual. Se estiveres a testar, cria alterações artificiais (editar um ficheiro de 1 KB) para ver o comportamento.
Conclusão
Aprendeste a criar e comparar snapshots de ficheiros em PowerShell, útil para auditoria e backups incrementais simples. Próximos passos possíveis: integrar notificações por email, sincronizar snapshots para OneDrive/SharePoint ou armazenar apenas metadados num sistema central. Dica prática: começa por testar numa pasta pequena (100–1 000 ficheiros) para validar filtros e desempenho. Qual pasta queres monitorizar primeiro?