(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como criar um snapshot de ficheiros em PowerShell: passo a passo

João Barros 31 de July de 2026 3 min de leitura

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?