Bash e gestione dei file: automatizzare operazioni ripetitive su Linux
Con il tempo, nella cartella Download o in una directory di lavoro possono accumularsi documenti, immagini, archivi compressi e file di testo. All’inizio riordinarli manualmente sembra semplice, ma quando i file diventano decine o centinaia, l’operazione può richiedere tempo e diventare soggetta a errori.
Linux mette a disposizione molti strumenti per lavorare con file e directory. Bash ci permette di combinarli in uno script, trasformando una sequenza di operazioni ripetitive in una procedura che possiamo riutilizzare quando serve.
In questa guida realizzeremo uno script che organizza i file di una cartella in sottodirectory basate sull’estensione: immagini in immagini, documenti PDF in pdf, archivi ZIP in archivi e così via. Lo costruiremo in modo prudente, prevedendo una modalità di prova che mostra le operazioni senza spostare nulla.
Prima di automatizzare, scegliamo bene la cartella
Quando uno script deve spostare o modificare file, la prima precauzione consiste nel definire con precisione dove può intervenire. Non vogliamo che una procedura pensata per riordinare alcuni documenti finisca per modificare file di sistema o contenuti importanti.
Per questo inizieremo con una directory di prova nella nostra cartella personale:
mkdir -p ~/prova-riordino
cd ~/prova-riordino
Creiamo alcuni file dimostrativi:
touch relazione.pdf
touch appunti.txt
touch fotografia.jpg
touch archivio.zip
touch "documento di prova.pdf"
Il comando touch, in questo caso, crea file vuoti se non esistono già. Non stiamo preparando documenti reali: ci basta avere nomi diversi su cui verificare il comportamento dello script, compreso un nome contenente spazi.
Possiamo controllare il contenuto della directory con:
ls -la
Questa verifica iniziale ci permette di sapere esattamente quali file dovremmo trovare dopo il riordino. È una buona abitudine ogni volta che proviamo un’automazione che modifica il filesystem.
Creiamo lo script Bash
Creiamo ora il file che conterrà la procedura:
nano riordina-file.sh
Inseriamo questo codice:
#!/usr/bin/env bash
set -u
CARTELLA="${1:-$PWD}"
MODALITA="${2:-prova}"
if [[ ! -d "$CARTELLA" ]]; then
echo "Errore: la directory indicata non esiste." >&2
exit 1
fi
if [[ "$MODALITA" != "prova" && "$MODALITA" != "esegui" ]]; then
echo "Uso: $0 [cartella] [prova|esegui]" >&2
exit 2
fi
shopt -s nullglob dotglob
for file in "$CARTELLA"/*; do
[[ -f "$file" ]] || continue
nome="${file##*/}"
# Ignora i file senza estensione utile.
[[ "$nome" == *.* && "$nome" != .* ]] || continue
estensione="${nome##*.}"
estensione="${estensione,,}"
case "$estensione" in
jpg|jpeg|png|gif|webp)
destinazione="immagini"
;;
pdf)
destinazione="pdf"
;;
txt|md|csv)
destinazione="testi"
;;
zip|tar|gz|xz|7z)
destinazione="archivi"
;;
*)
continue
;;
esac
cartella_dest="$CARTELLA/$destinazione"
nuovo_percorso="$cartella_dest/$nome"
if [[ -e "$nuovo_percorso" ]]; then
echo "Saltato: destinazione già esistente per $nome"
continue
fi
if [[ "$MODALITA" == "prova" ]]; then
printf 'Sposterei: %s -> %s\n' "$file" "$nuovo_percorso"
else
mkdir -p -- "$cartella_dest" || {
echo "Errore nella creazione di $cartella_dest" >&2
continue
}
if mv -n -- "$file" "$cartella_dest/"; then
printf 'Spostato: %s -> %s\n' "$nome" "$destinazione"
else
echo "Errore durante lo spostamento di $nome" >&2
fi
fi
done
echo "Operazione terminata."
Salviamo con Ctrl+O, confermiamo con Invio e usciamo con Ctrl+X.
Il codice può sembrare lungo rispetto all’operazione da svolgere, ma le verifiche aggiuntive hanno uno scopo preciso: limitare gli interventi ai file previsti, gestire i nomi con spazi, evitare di sovrascrivere intenzionalmente un file già presente e permetterci di controllare il risultato prima di procedere.
Come funziona lo script
La prima parte controlla gli argomenti ricevuti. Se non indichiamo una directory, viene utilizzata quella corrente; se non specifichiamo una modalità, lo script lavora in modalità prova.
La verifica [[ ! -d "$CARTELLA" ]] controlla che la directory esista. Le virgolette attorno alle variabili sono importanti: impediscono che un percorso contenente spazi venga interpretato come più argomenti distinti.
Successivamente utilizziamo nullglob e dotglob. La prima opzione evita che un modello senza corrispondenze venga restituito come testo letterale; la seconda permette di includere anche i nomi nascosti nell’iterazione. Lo script, tuttavia, ignora i nomi che iniziano con un punto quando cerca un’estensione, per non trattare automaticamente i file nascosti come documenti da classificare.
Il ciclo for esamina gli elementi della directory, mentre [[ -f "$file" ]] seleziona soltanto i file regolari, escludendo le sottodirectory. In questo modo non entriamo ricorsivamente nelle cartelle che abbiamo appena creato.
La parte case decide dove collocare ciascun file. Le estensioni vengono trasformate in minuscolo con ${estensione,,}, una funzionalità di Bash che ci permette di gestire allo stesso modo, per esempio, FOTO.JPG e foto.jpg.
Infine, lo script verifica se esiste già un file con lo stesso nome nella destinazione. Se lo trova, salta quel file anziché tentare di sostituirlo. La modalità di prova mostra invece ciò che verrebbe spostato senza creare directory e senza modificare i file.
Proviamo lo script senza spostare nulla
Prima di eseguire qualsiasi modifica, rendiamo il file eseguibile:
chmod +x riordina-file.sh
Ora possiamo avviare lo script nella directory di prova:
./riordina-file.sh "$HOME/prova-riordino" prova
Vedremo messaggi simili a questi:
Sposterei: /home/utente/prova-riordino/relazione.pdf -> /home/utente/prova-riordino/pdf/relazione.pdf
Sposterei: /home/utente/prova-riordino/fotografia.jpg -> /home/utente/prova-riordino/immagini/fotografia.jpg
Operazione terminata.
I percorsi e l’ordine dei risultati possono essere diversi. La cosa importante è che i file siano ancora al loro posto: in modalità prova lo script non deve spostarli.
Controlliamo con ls -la e confrontiamo i risultati con l’elenco iniziale. Se vediamo una destinazione sbagliata, possiamo modificare le regole nel blocco case senza dover recuperare file già spostati.
Quando siamo pronti, eseguiamo il riordino
Se la simulazione corrisponde al risultato desiderato, possiamo passare alla modalità operativa:
./riordina-file.sh "$HOME/prova-riordino" esegui
Questa volta lo script crea le sottodirectory necessarie e sposta i file classificati. I file senza estensione, quelli con estensioni non previste e le directory non vengono spostati.
Il controllo delle destinazioni esistenti riduce il rischio di collisioni. In ogni caso, mv -n è una precauzione aggiuntiva, non una garanzia universale contro ogni situazione imprevista: il comportamento preciso dipende anche dall’ambiente e dal sistema di file. Per questo è importante provare sempre la procedura su dati non importanti e conservare una copia dei contenuti originali prima di applicarla a una cartella reale.
Il nostro esempio non analizza il contenuto dei file: si basa soltanto sul nome e sull’estensione. Un file chiamato documento.pdf non è necessariamente un PDF valido, così come un file senza estensione potrebbe essere un documento importante. L’automazione è utile quando le regole sono chiare, ma non sostituisce il buon senso nella classificazione dei dati.
Come estendere l’automazione in modo sicuro
Una volta compreso il funzionamento, possiamo aggiungere altre estensioni al blocco case, creare categorie specifiche per il nostro lavoro o modificare lo script per generare un rapporto delle operazioni effettuate.
Se invece dobbiamo cercare file in molte directory, filtrare in base alla data di modifica o elaborare il contenuto dei documenti, strumenti come find, grep, awk e xargs possono essere più adatti. Nella nostra guida dedicata alla ricerca e modifica dei testi con Bash approfondiamo proprio queste possibilità.
Quando l’obiettivo diventa creare copie di sicurezza anziché spostare file, è preferibile adottare una procedura specifica per il backup, con strumenti come rsync e tar. Possiamo approfondire il tema nella guida alla creazione di archivi e backup automatici con Bash.
In entrambi i casi, il principio resta lo stesso: partire da un’operazione semplice, verificarne il comportamento e aggiungere complessità solo quando è davvero necessaria.
Conclusioni
Bash ci permette di trasformare operazioni ripetitive sui file in procedure riproducibili. Con lo script realizzato abbiamo organizzato una directory in base alle estensioni, gestito i nomi contenenti spazi e previsto una modalità di prova prima di effettuare modifiche.
L’aspetto più importante non è soltanto sapere come spostare i file con un comando. È imparare a costruire automazioni che dichiarano chiaramente dove possono intervenire, controllano le condizioni iniziali e rendono verificabile il risultato.
Possiamo applicare lo stesso metodo a molte altre attività di amministrazione Linux: prima definiamo le regole, poi proviamo su dati non importanti e infine automatizziamo il lavoro reale, mantenendo sempre la possibilità di controllare ciò che sta accadendo.
LICENZA E CONDIZIONI D’USO
Questo How-to è rilasciato sotto licenza Creative Commons Attribution-NonCommercial 3.0 Italy.
CONTATTI DELL’AUTORE
Marco Ciammella marco@orvietolinux.it
Orvieto Linux User Group info@orvietolinux.it