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

Cómo crear un snapshot de archivos en PowerShell: paso a paso

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

Este tutorial muestra cómo crear un snapshot de archivos en PowerShell para registrar el estado de una carpeta, detectar cambios y facilitar reversiones. Es una técnica simple y eficaz para auditoría, detección de cambios no deseados y backups incrementales en entornos donde no existe un sistema de versionado más avanzado. En entornos reales, un snapshot por día puede ser suficiente; en entornos sensibles, puedes ejecutar este proceso cada hora. Los ejemplos concretos abajo muestran cómo generar, comparar y automatizar snapshots.

Requisitos previos

  • Windows con PowerShell 5.1 o PowerShell 7+
  • Permisos de lectura/escritura en la carpeta objetivo (al menos lectura para todos los archivos a monitorizar, escritura si vas a guardar snapshots)
  • Conocimientos básicos de PowerShell (cmdlets como Get-ChildItem, Get-FileHash, Export-Csv)

Nota sobre rendimiento: calcular hashes de archivos grandes depende de I/O y CPU. Por ejemplo, en disco SSD una máquina moderna puede calcular SHA256 a ~100 MB/s; 10 GB de archivos pueden tardar ~100 segundos en lectura pura. Prueba en una carpeta pequeña (100–1000 archivos) antes de escalar a 50k archivos.

Paso 1: Elegir la carpeta y el formato del snapshot

Decide qué carpeta vas a monitorizar y el formato del snapshot. Aquí usamos un CSV simple con campos: RelativePath, FullPath, Length, LastWriteTime y Hash (SHA256). El CSV es portátil y fácil de comparar con Import-Csv o Excel. Guardar la marca de fecha/hora en formato ISO 8601 ('o') facilita ordenación y parsing automático.

Ejemplo de dimensionamiento: un snapshot de 10k archivos (5 campos) tiende a quedarse entre 1–5 MB dependiendo de la longitud de las rutas. Si necesitas compresión, guarda los CSV en .zip o usa gzip forzado por otras herramientas.

Paso 2: Script básico para generar el snapshot

Crea un script que recorra la carpeta de forma recursiva, calcule el hash de cada archivo y escriba un CSV. El hash detecta cambios de contenido incluso si la marca de tiempo no cambia. Usa SHA256 en lugar de SHA1, que hoy en día es menos recomendable.

# 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

Guárdalo como GerarSnapshot.ps1. Ejecuta: .\GerarSnapshot.ps1 -Folder C:\\Dados -SnapshotPath C:\\snapshots\\snap1.csv. En un ejemplo práctico, un conjunto de 2 000 archivos (total 2 GB) puede tardar 1–3 minutos en generar el snapshot dependiendo del disco.

Paso 3: Comparar dos snapshots

Para detectar archivos añadidos, eliminados o modificados, carga dos CSV y haz una comparación por RelativePath y Hash. El método abajo usa Compare-Object para cambios en la lista de rutas y una comparación adicional para cambios de contenido (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

# Archivos nuevos
$added = Compare-Object -ReferenceObject $old -DifferenceObject $new -Property RelativePath -PassThru | Where-Object {$_.PSObject.Properties['SideIndicator'].Value -eq '=>'}
# Archivos eliminados
$removed = Compare-Object -ReferenceObject $old -DifferenceObject $new -Property RelativePath -PassThru | Where-Object {$_.PSObject.Properties['SideIndicator'].Value -eq '<='}

# Archivos con la misma ruta pero hash diferente -> modificados
$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 simple
[PSCustomObject]@{
    Added = $added.Count
    Removed = $removed.Count
    Modified = $joined.Count
}

# Lista detallada (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 }

Ejecuta: .\CompararSnapshots.ps1 -OldSnapshot C:\\snapshots\\snap1.csv -NewSnapshot C:\\snapshots\\snap2.csv. Un resultado típico puede ser: Added = 5, Removed = 2, Modified = 10. Revisa las listas detalladas para confirmar los cambios.

Paso 4: Ignorar archivos que cambian con frecuencia

Algunas carpetas tienen archivos temporales (logs, caches) que solo generan ruido. Filtra por extensión, patrón o tamaño antes de calcular el hash para reducir tiempo y ruido. Por ejemplo, evita *.log, *.tmp y archivos de menos de 1 KB.

# Ejemplo de filtro en 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 { ... }

Este enfoque reduce significativamente el tiempo: al excluir el 30% de los archivos temporales, la generación del snapshot puede pasar de 10 minutos a 7 minutos en un ejemplo con muchas pequeñas modificaciones.

Paso 5: Automatizar y preservar historiales

Puedes ejecutar el script regularmente con el Task Scheduler (p. ej.: diariamente o cada hora) y guardar snapshots con timestamp en el nombre. Mantén solo los N últimos para no llenar el disco; 7 es un buen valor para retención semanal.

# Ejemplo para guardar con timestamp
$ts = (Get-Date).ToString('yyyyMMddHHmmss')
.\GerarSnapshot.ps1 -Folder C:\\Dados -SnapshotPath C:\\snapshots\\snapshot_$ts.csv

# Eliminar snapshots antiguos, queda solo los 7 más recientes
Get-ChildItem C:\\snapshots -Filter 'snapshot_*.csv' | Sort-Object LastWriteTime -Descending | Select-Object -Skip 7 | Remove-Item

Programación práctica: crea una Task que ejecute el script a las 02:00 o en horarios de baja utilización. Si la carpeta tiene muchos archivos, define una alerta por email en caso de fallo (p. ej.: integración con Send-MailMessage o sistemas de monitorización).

Verificar el resultado

Confirma que los CSV se han generado y que la comparación muestra números coherentes. Abre los CSV en Excel o usa Import-Csv para inspeccionar. Haz una verificación manual en algunos archivos listados en Added/Removed/Modified: por ejemplo, usa Get-FileHash en el archivo específico para confirmar el hash actual. Si estás probando, crea cambios artificiales (editar un archivo de 1 KB) para ver el comportamiento.

Conclusión

Has aprendido a crear y comparar snapshots de archivos en PowerShell, útil para auditoría y backups incrementales simples. Próximos pasos posibles: integrar notificaciones por email, sincronizar snapshots a OneDrive/SharePoint o almacenar solo metadatos en un sistema central. Consejo práctico: empieza probando en una carpeta pequeña (100–1 000 archivos) para validar filtros y rendimiento. ¿Qué carpeta quieres monitorizar primero?