Corso Python / Copiare file con dry-run e verifica del contenuto
Per iniziare un’automazione di file, separa l’elenco delle operazioni previste dalla loro esecuzione. In questo esercizio il comando senza opzioni mostra una dry-run, cioè un’anteprima senza copiare; --apply copia i file di testo e rifiuta destinazioni già esistenti.
Preparare dati separati e una politica di conservazione
Lavora in una cartella nuova riservata alla prova, con l’interprete del progetto selezionato. I percorsi copy-demo/in e copy-demo/out sono relativi alla cartella di lavoro: verifica dove si trovano prima di eseguire il programma. Non usare una cartella con documenti importanti per questa esercitazione.
Il programma copia, senza spostare o eliminare gli originali. Cerca solo i file *.txt direttamente nella cartella in, non nelle sottocartelle, e scarta le voci che risultano collegamenti simbolici. Sceglie di fermarsi su un conflitto di nome, invece di sovrascrivere o inventare automaticamente un nuovo nome.
Salva questo primo programma completo come setup_copy.py, in UTF-8, ed esegui una sola volta python setup_copy.py nella cartella nuova. Questa preparazione scrive il file dimostrativo; è distinta dalla successiva dry-run.
from pathlib import Path
source = Path("copy-demo/in")
source.mkdir(parents=True, exist_ok=True)
with (source / "note.txt").open("x", encoding="utf-8") as f:
f.write("demo\n")
print("sample ready")
Deve comparire sample ready e deve esistere copy-demo/in/note.txt. La modalità x rifiuta una seconda creazione dello stesso file, quindi non sostituisce una prova già esistente. Se la preparazione fallisce per un conflitto, controlla il percorso e scegli una nuova cartella di esercizio.
Shutil fornisce le operazioni di copia; la documentazione ufficiale di shutil distingue la copia dei contenuti dalla conservazione dei metadati. Il significato dei percorsi relativi è spiegato nella guida a pathlib.
Controllare l’anteprima senza creare la destinazione
Salva il programma seguente come safe_copy.py, in UTF-8, nella stessa cartella. Dopo la preparazione esegui python safe_copy.py. Fuori dall’ambiente virtuale su macOS o Ubuntu usa python3 se è il comando dell’interprete scelto. Tutti i moduli usati appartengono alla libreria standard.
import argparse
import hashlib
import shutil
from pathlib import Path
parser = argparse.ArgumentParser()
parser.add_argument("--apply", action="store_true")
args = parser.parse_args()
source, target = Path("copy-demo/in"), Path("copy-demo/out")
if not source.is_dir():
parser.error("prepare copy-demo/in first")
files = sorted(p for p in source.glob("*.txt") if p.is_file() and not p.is_symlink())
for src in files:
dst = target / src.name
if dst.exists() or dst.is_symlink():
raise FileExistsError(dst)
print("copy", src.name)
if args.apply:
target.mkdir(parents=True, exist_ok=True)
with src.open("rb") as incoming, dst.open("xb") as outgoing:
shutil.copyfileobj(incoming, outgoing)
if hashlib.sha256(src.read_bytes()).digest() != hashlib.sha256(dst.read_bytes()).digest():
raise RuntimeError("copy verification failed")
print("applied" if args.apply else "dry-run")
Con il solo file dimostrativo preparato e nessuna destinazione esistente, l’output è:
copy note.txt
dry-run
In questa fase copy-demo/out non deve essere creato. Il comando controlla comunque le condizioni: se manca la cartella di origine, argparse segnala prepare copy-demo/in first e termina; se una destinazione esiste già, anche la dry-run può fermarsi con FileExistsError invece di approvare un elenco non applicabile.
Il messaggio copy indica il file selezionato e non dimostra da solo che sia stato copiato. Guarda l’ultima riga e verifica i file effettivi: senza --apply è soltanto una previsione. Anche applied con un ingresso privo di file corrispondenti non dimostra che sia stata creata una copia.
Applicare la copia e confrontare i byte
Dopo aver controllato elenco e percorsi, esegui:
python safe_copy.py --apply
La prima esecuzione deve stampare copy note.txt seguito da applied e creare copy-demo/out/note.txt. L’apertura in xb crea esclusivamente un file nuovo: se la destinazione è stata creata dopo il controllo preliminare, l’apertura continua a rifiutarne la sostituzione.
shutil.copyfileobj trasferisce i byte tra file aperti in modalità binaria. Uscendo dal blocco with, entrambi i file vengono chiusi prima della lettura usata per la verifica. Il confronto SHA-256 controlla che i contenuti del piccolo file dimostrativo coincidano; non verifica automaticamente proprietario, permessi, flussi aggiuntivi o tutti i metadati.
- Esegui la dry-run nella cartella preparata e controlla che out non esista.
- Esegui --apply e apri la copia: deve contenere demo e il fine riga previsto. Il file originale deve essere ancora presente e invariato.
- Ripeti --apply sulla stessa destinazione: deve fermarsi con FileExistsError senza sostituire la copia precedente.
Se vuoi ripetere la prova dall’inizio senza alterare i risultati, usa una nuova cartella di esercizio. Non aggiungere una cancellazione automatica soltanto per far passare la ripetizione.
Gestire fallimenti e limiti prima di estendere lo strumento
Una copia interrotta può lasciare un file parziale. Alla ripetizione xb ne impedirà la sostituzione: controlla percorso assoluto e contenuto prima di definire come recuperare. Il programma non effettua rollback dell’intero gruppo; se copia un file e incontra poi un conflitto su un altro, la prima copia resta. Una previsione riuscita non è inoltre una prenotazione dei percorsi fino all’esecuzione.
La verifica degli hash usa read_bytes e carica ogni piccolo file per intero. Per file grandi, calcola gli hash in blocchi e definisci come trattare modifiche dell’origine durante la copia. L’esempio esclude singole voci simboliche, ma non protegge da un utente non attendibile che sostituisca contemporaneamente le cartelle genitrici: non presentarlo come isolamento di sicurezza per un file system ostile.
La gestione delle eccezioni serve a distinguere conflitti, problemi di accesso e altre condizioni, conservando il segnale del fallimento. Prima di introdurre rinomina, spostamento o eliminazione, progetta inventario dei cambiamenti, backup e recupero. Per la pulizia finale verifica che ogni percorso assoluto risolto appartenga davvero alla cartella dimostrativa e intervieni solo sui risultati che hai identificato.




