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 arquivos 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.
Foram verificados manualmente os tamanhos dos quatro arquivos sintéticos como 6, 5, 6 e 10 bytes.
Foi calculado manualmente o total descompactado da origem como 27 bytes.
Foram listados manualmente os caminhos esperados dos membros do arquivo, incluindo os dois caminhos aninhados de reports.
O código foi inspecionado para confirmar que os arquivos de origem são lidos, o ZIP é gravado dentro de outputs e um arquivo datado já existente faz a execução parar.
A lógica de verificação foi inspecionada quanto ao teste CRC, comparação da lista de membros, comparação do tamanho descompactado e comparação SHA-256.
O nome esperado do arquivo para 2026-09-20 e a saída do console foram derivados manualmente.
Limites da verificação
O código não foi executado pelo autor desta resposta; nenhum arquivo ZIP foi criado nem aberto.
Os valores SHA-256 e os resultados CRC não foram calculados manualmente porque a lógica de comparação é a verificação relevante para este exemplo.
Alterações simultâneas na origem, falhas de permissão, corrupção de armazenamento, gravações interrompidas, links simbólicos e desempenho em diretórios grandes não foram testados.
O tamanho compactado do arquivo não foi previsto porque depende do resultado da compactação e dos metadados ZIP.
As URLs da documentação oficial foram fornecidas com base em locais de documentação conhecidos, mas não foram verificadas ao vivo.
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.