A volte si ha la necessità di dover cancellare tutti i file contenuti contenuti in una directory eccetto uno o più file con un certo nome o con una particolare estensione.
In questo articolo trattiamo 3 modi per cancellare tutti i file presenti in una cartella escludendo quelli di un certo tipo e per farlo utilizziamo i comandi rm, find e globignore.
Tabella dei Contenuti
Filename pattern matching
Prima di addentrarci nell’uso dei comandi, diamo uno sguardo ad un concetto fondamentale in Linux, ossia il filename pattern matching, che ci permette di affrontare agevolmente il problema in questione.
In Linux esistono i cosidetti shell pattern, delle stringhe composte dai seguenti caratteri speciali denominati anche wildcards o metacharacters:
- * – zero o più caratteri
- ? – un singolo carattere
- [seq] – qualsiasi carattere che compone seq
- [!seq] – qualsiasi carattere non incluso in seq
Cancellare file usando gli Extended Pattern Matching Operators
Questi operatori estesi permettono di eseguire un pattern matching articolato. Facendo seguire i caratteri wildcards da una pattern-list, ossia una lista contenente uno o più filename separati usando il carattere |
.
*(pattern-list)
– zero o più occorrenze di uno specifico pattern?(pattern-list)
– zero o una occorrenza di uno specifico pattern+(pattern-list)
– una o più occorrenze di uno specifico pattern@(pattern-list) - uno tra i pattern specificati
!(pattern-list) - qualsiasi cosa tranne il pattern specificato
Per poter utilizzare questi operatori avanzati dobbiamo preventivamente attivare l’opzione di shell extglob:
shopt -s extglob
Cancellare tutti i file tranne uno specifico
Il seguente comando permette di cancellare tutti i file della directory tranne quello specificato tra parentesi.
rm -v !("filename")
Cancellare tutti i file tranne una lista di specifici
Utilizzando l’operatore | possiamo concatenare tutti i nomi dei file che vogliamo preservare dalla cancellazione.
rm -v !("filename1"|"filename2"|"...")
Cancellare tutti i file tranne quelli con una certa estensione
In questo esempio cancelliamo tutti i file diversi dagli archivi .zip
rm -i !(*.zip)
Estendendo il concetto visto prima, possiamo utilizzare l’operatore | per escludere dalla cancellazione sia gli archivi .zip che i file .odt
rm -i !(*.zip|*.odt)
Disabilitare gli operatori avanzati di pattern matching
Una volta che abbiamo terminato di utilizzare gli operatori avanzati disabilitiamoli con questo comando:
shopt -u extglob
Cancellare file con il comando find
Utilizzando il comando find di Linux con le appropriate opzioni o in combinazione con il comando xargs possiamo ottenere degli ottimi risultati.
find /directory/ -type f -not -name 'PATTERN' -delete
find /directory/ -type f -not -name 'PATTERN' -print0 | xargs -0 -I {} rm {}
find /directory/ -type f -not -name 'PATTERN' -print0 | xargs -0 -I {} rm [options] {}
Cancellare tutti i file tranne quelli con una certa estensione
Riprendendo l’esempio di prima, cancelliamo tutti i file diversi che non sono archivi .zip
find . -type f -not -name '*.zip'-delete
Allo stesso modo possiamo utilizzare find in combinazione con xargs
find . -type f -not -name '*.zip' -print0 | xargs -0 -I {} rm -v {}
Cancellare tutti i file tranne una serie con una certa estensione
find . -type f -not \(-name '*.zip' -or -name '*.odt' -or -name '*.jpg' \) -delete
Cancellare file sfruttando la variabile Bash GLOBIGNORE
L’ultimo approccio al problema che vediamo in questo articolo sfrutta la variabile Bash GLOBIGNORE, la quale memorizza una pattern-list (filenames) separata dal carattere dei due punti.
Come prima cosa istanziamo la variabile indicando i nomi dei file che vogliamo escludere. In questo esempio escludiamo i file con le seguenti estensioni:
GLOBIGNORE=*.odt:*.iso:*.txt
A questo punto possiamo eseguire in sicurezza il comando per eliminare tutti i file presenti in cartella:
rm -v *
Una volta che abbiamo terminato il task, ricordiamoci di ripristinare la normalità spegnendo la variabile GLOBEIGNORE:
unset GLOBIGNORE