Crie um backup ZIP com data e verifique o que foi arquivado
Crie um arquivo ZIP com data a partir de uma pasta sem alterar os originais e verifique se todos os arquivos de origem aparecem no arquivo com conteúdo correspondente. Uma pequena pasta sintética facilita a conferência manual dos caminhos, tamanhos e totais esperados.
Conteúdo verificado 2026.09.20Inclui código de exemplo
Ver o sumário
A tradução foi feita com IA. Confira o código, as unidades e os valores junto com o original. A revisão por falantes nativos de cada idioma ainda não foi concluída. English
Para quem éEste guia é voltado a pessoas que querem um backup simples de pasta com data e uma etapa explícita de verificação, em vez de presumir que a criação do arquivo foi bem-sucedida.
Preparação
Python 3.12 e um comando de terminal que inicie essa versão.
Uma pasta de trabalho em que os scripts possam criar pastas dentro de outputs.
Permissão de leitura para os arquivos de origem e espaço em disco suficiente para o arquivo ZIP.
É necessária apenas a biblioteca padrão do Python: datetime, hashlib, pathlib e zipfile.
01Defina o que o backup deve conter
O script arquivará arquivos regulares de uma pasta de origem, incluindo arquivos em subpastas aninhadas. Os caminhos dentro do ZIP são armazenados em relação à pasta de origem, portanto um arquivo como reports/week1.txt permanece reports/week1.txt em vez de se tornar um caminho absoluto do sistema de arquivos.
O nome do arquivo contém a data atual do calendário local no formato YYYY-MM-DD. Se o exemplo for executado em 2026-09-20, o nome esperado será backup_demo_2026-09-20.zip. Executá-lo novamente no mesmo dia com o mesmo destino faz o script parar em vez de substituir o backup anterior.
02Crie uma pasta de origem sintética
O conjunto de dados a seguir é sintético e foi criado especificamente para este artigo. Salve o script de preparação como create_backup_demo.py. Ele cria quatro arquivos com conteúdo exato em bytes, incluindo um arquivo em uma pasta reports aninhada.
python
from pathlib import Path
SOURCE = Path("outputs") / "backup_demo"
FILES = {
"notes.txt": b"alpha\n",
"reports/week1.txt": b"beta\n",
"reports/week2.txt": b"gamma\n",
"settings.ini": b"mode=test\n",
}
SOURCE.parent.mkdir(parents=True, exist_ok=True)
SOURCE.mkdir() # Stop if the synthetic source already exists.
for relative_name, content in FILES.items():
target = SOURCE / relative_name
target.parent.mkdir(parents=True, exist_ok=True)
with target.open("xb") as stream:
stream.write(content)
text
python create_backup_demo.py
Caminho relativo
Conteúdo exato
Bytes
notes.txt
alpha mais quebra de linha
6
reports/week1.txt
beta mais quebra de linha
5
reports/week2.txt
gamma mais quebra de linha
6
settings.ini
mode=test mais quebra de linha
10
A origem contém 4 arquivos regulares totalizando 27 bytes de conteúdo descompactado: 6 + 5 + 6 + 10. O tamanho final do próprio arquivo ZIP não pode ser previsto a partir desse total porque a compactação ZIP e os metadados do arquivo adicionam sua própria sobrecarga.
03Prepare a execução do backup com data
Salve o script principal como dated_zip_backup.py ao lado do script de preparação.
Mantenha SOURCE como outputs/backup_demo neste exemplo.
Mantenha BACKUP_DIR como outputs/backups para que o arquivo fique fora da pasta de origem.
Execute o script a partir do mesmo diretório de trabalho.
text
python dated_zip_backup.py
O script verifica se a origem existe e se o diretório de backup não está dentro do diretório de origem. A pasta pai do backup pode já existir. O próprio arquivo ZIP com data não pode existir.
04Crie o ZIP e verifique cada membro
O script primeiro cria uma lista ordenada dos arquivos de origem. Ele cria o arquivo usando criação exclusiva, grava cada arquivo com compactação ZIP_DEFLATED e depois reabre o arquivo para verificação. A verificação compara a lista de membros pretendida, testa a integridade CRC com testzip e compara os hashes SHA-256 dos arquivos de origem e arquivados.
python
from datetime import date
import hashlib
from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile
SOURCE = Path("outputs") / "backup_demo"
BACKUP_DIR = Path("outputs") / "backups"
CHUNK_SIZE = 1024 * 1024
def hash_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
while chunk := stream.read(CHUNK_SIZE):
digest.update(chunk)
return digest.hexdigest()
def hash_member(archive: ZipFile, member_name: str) -> str:
digest = hashlib.sha256()
with archive.open(member_name, "r") as stream:
while chunk := stream.read(CHUNK_SIZE):
digest.update(chunk)
return digest.hexdigest()
def main() -> None:
source_root = SOURCE.resolve(strict=True)
if not source_root.is_dir():
raise ValueError("SOURCE must be a directory.")
backup_root = BACKUP_DIR.resolve()
if backup_root.is_relative_to(source_root):
raise ValueError("BACKUP_DIR must be outside SOURCE.")
files = sorted(
path for path in source_root.rglob("*")
if path.is_file() and not path.is_symlink()
)
if not files:
raise ValueError("SOURCE contains no regular files to back up.")
BACKUP_DIR.mkdir(parents=True, exist_ok=True)
archive_name = f"{source_root.name}_{date.today().isoformat()}.zip"
archive_path = BACKUP_DIR / archive_name
if archive_path.exists():
raise FileExistsError(f"Backup already exists: {archive_path}")
expected = {}
with archive_path.open("xb") as raw:
with ZipFile(raw, "w", compression=ZIP_DEFLATED) as archive:
for path in files:
relative = path.relative_to(source_root).as_posix()
expected[relative] = (path.stat().st_size, hash_file(path))
archive.write(path, arcname=relative)
with ZipFile(archive_path, "r") as archive:
bad_member = archive.testzip()
if bad_member is not None:
raise RuntimeError(f"CRC check failed: {bad_member}")
members = [info for info in archive.infolist() if not info.is_dir()]
actual_names = [info.filename for info in members]
expected_names = list(expected)
if actual_names != expected_names:
raise RuntimeError("Archive member list does not match the source list.")
for info in members:
expected_size, expected_hash = expected[info.filename]
if info.file_size != expected_size:
raise RuntimeError(f"Size mismatch: {info.filename}")
if hash_member(archive, info.filename) != expected_hash:
raise RuntimeError(f"Hash mismatch: {info.filename}")
total_bytes = sum(size for size, _ in expected.values())
print(f"Verified {len(expected)} files totaling {total_bytes} bytes.")
print(f"Archive: {archive_path.as_posix()}")
if __name__ == "__main__":
main()
O código ignora links simbólicos e arquiva apenas arquivos regulares. Os hashes esperados são calculados a partir da origem imediatamente antes de cada arquivo ser adicionado. Para uma pasta local normal que permaneça inalterada durante a execução, isso fornece uma comparação útil em nível de conteúdo após a criação do arquivo.
05Verifique manualmente o arquivo esperado
Se o script for executado em 2026-09-20, o caminho esperado do arquivo será outputs/backups/backup_demo_2026-09-20.zip. O ZIP deve conter exatamente os quatro caminhos de membros abaixo.
Membro do arquivo
Bytes descompactados
notes.txt
6
reports/week1.txt
5
reports/week2.txt
6
settings.ini
10
A pasta reports aninhada é representada pelos próprios caminhos dos membros. O script não precisa de uma entrada de diretório separada para reports porque os arquivos já carregam esse caminho relativo.
A saída esperada do console abaixo foi derivada manualmente para uma execução em 2026-09-20. Não é um log capturado de execução.
Abra o ZIP em um visualizador de arquivos compactados e confirme que há exatamente 4 arquivos com os caminhos relativos esperados.
Extraia o arquivo para um local temporário separado e compare o conteúdo de texto com os 4 arquivos de origem.
Confirme que os arquivos originais ainda existem em outputs/backup_demo depois que o backup for concluído.
Execute novamente o script de backup na mesma data sem alterar o destino. Ele deve parar com FileExistsError em vez de substituir o arquivo existente.
Se quiser confirmar que a verificação acompanha o novo conteúdo, altere uma cópia de um arquivo de origem em um teste separado e crie um novo backup com um nome de arquivo diferente.
Não use o tamanho do arquivo compactado como verificação principal. A compactação significa que um arquivo válido pode ser menor ou maior do que o total descompactado da origem, dependendo dos dados e dos metadados.
07Reconheça erros comuns
Sintoma
O que verificar
FileNotFoundError
Verifique SOURCE e o diretório de trabalho do terminal. Neste exemplo, execute primeiro o script de preparação sintético.
FileExistsError
Já existe um backup com o mesmo nome datado. Revise-o e escolha outro destino ou aguarde outra data de backup pretendida em vez de sobrescrevê-lo.
PermissionError
Confirme que o script consegue ler todos os arquivos de origem e criar arquivos dentro de BACKUP_DIR.
CRC check failed
Trate o arquivo como falho. Não dependa dele como backup; investigue erros de armazenamento ou gravação e crie um novo arquivo.
Member list mismatch
A origem pode ter sido alterada durante a execução, ou o conteúdo do arquivo pode não corresponder à lista de arquivos montada no início.
Hash or size mismatch
Trate a verificação como falha. Mantenha a origem original inalterada e crie um novo arquivo após investigar a divergência.
Se ocorrer uma exceção depois que o arquivo ZIP tiver sido criado, um arquivo parcial ou não verificado pode permanecer na pasta de backups. O script não o exclui automaticamente porque uma limpeza automática pode ocultar evidências úteis para diagnosticar a falha.
08Entenda o que este backup não garante
Este é um fluxo de arquivamento por cópia de arquivos, não um snapshot transacional do sistema de arquivos. Se outro aplicativo modificar um arquivo enquanto ele estiver sendo calculado por hash ou arquivado, o resultado pode ficar inconsistente. Para dados importantes, interrompa as gravações na origem ou use um sistema de backup com suporte a snapshots.
O exemplo não preserva todas as propriedades do sistema de arquivos. Permissões, propriedade, listas de controle de acesso, atributos estendidos, fluxos de dados alternativos, links simbólicos e metadados específicos de aplicativos podem exigir outra ferramenta de backup. ZIP é útil para coleções portáteis de arquivos, mas não é uma imagem completa de um sistema de arquivos.
Um arquivo verificado ainda é apenas uma cópia. Um plano real de backup deve considerar múltiplas cópias, falhas de armazenamento, exclusão acidental, ransomware, períodos de retenção, criptografia e se a recuperação foi realmente testada. A verificação aqui mostra que este arquivo correspondeu ao conteúdo da origem observado durante esta execução; ela não estabelece uma estratégia completa de recuperação de desastres.
A origem sintética continha exatamente 4 arquivos regulares, totalizando 27 bytes: notes.txt=6, reports/week1.txt=5, reports/week2.txt=6, settings.ini=10.
A execução real imprimiu 'Verified 4 files totaling 27 bytes.' e 'Archive: outputs/backups/backup_demo_2026-09-21.zip'.
O nome de arquivo e o exemplo de console com 2026-09-20 no artigo são explicitamente condicionados à execução do script em 2026-09-20; o ambiente de execução usou corretamente a data local real, 2026-09-21.
O ZIP continha exatamente notes.txt, reports/week1.txt, reports/week2.txt e settings.ini na ordem esperada.
Os tamanhos descompactados dos membros do ZIP eram exatamente 6, 5, 6 e 10 bytes.
ZipFile.testzip() não retornou nenhum membro inválido.
Os valores SHA-256 de todos os membros arquivados correspondiam aos respectivos arquivos de origem.
Todos os hashes SHA-256 dos arquivos de origem permaneceram inalterados após a criação do arquivo compactado.
Executar novamente o script com o mesmo arquivo datado já existente gerou FileExistsError em vez de substituí-lo.
Limites da verificação
Não foram realizados testes de estresse para modificação simultânea da origem, falhas de permissão, corrupção de armazenamento, gravações interrompidas, casos extremos com links simbólicos, preservação de metadados do sistema de arquivos nem desempenho em diretórios grandes.
Fontes de referência
As explicações e os exemplos são de elaboração própria. Os comportamentos e conceitos relacionados podem ser consultados nas fontes oficiais abaixo.
Percorra subpastas e registre caminhos, extensões, tamanhos e datas de modificação dos arquivos em uma tabela. Comece com 4 pequenos arquivos de exemplo, mantendo os originais e os resultados existentes intactos.
Combine em ordem arquivos CSV com a mesma estrutura de colunas e adicione uma coluna source_file. Use conjuntos de dados pequenos para verificar nomes de itens com vírgulas, colunas ausentes e saídas já existentes.