Rinominare più file in un colpo solo: piccolo script bash


Vi è mai successo di dover rinominare tutti i file di una cartella, anche solo per cambiare estensione ? Se no, meglio per voi, se si, vi sarete accorti che, da console, non è così immediato; infatti, il comando mv da solo non basta.

Provo ad aiutarvi con questo:

for oldfile in *.txt; do cp “$oldfile” “`basename “$oldfile”.txt`.html”; done

Questa è una breve linea di  shell scripting  buona per Bourne Shell (sh), Bourne Again Shall (bash), la Z Shell (zsh), ma non  nelle C Shell e TC Shell (cshtcsh rispettivamente). Cosa fa ? copia tutti file, presenti nella cartella in cui ci si trova, con estensione txt, con la nuova ‘estensione html.

Comando per comando

Vediamo in dettagli il comando:

for oldfile in *.txt; do

Crea un ciclo mettendo, nella variabile oldfile, tutti i file presenti nell’attuale cartella, con estensione txt.

basename “$oldfile” .txt

(siamo dentro al ciclo, nel comando cp) Prendi il valore della variabile oldfile (l’operatore $ indica di usare il valore), estrai il nome eliminando la desinenza .txt. Nota: il punto(.) deve essere incluso; inoltre lasciare lo spazio tra $oldfile e .txt, visto che basename è un comando e $oldfile e .txt i parametri. Per maggiori informazioni, man basename.

cp “$oldfile” “`basename “$oldfile” .txt`.html”;

Premetto che l’apice al contrario (`) nella tastera italiana si inseriscono con ALT+96. E’ fondamentale, da non confondere con l’apice singolo “tradizionale” (’). In pratica, quando la shell trova qualcosa tra due apici rovesciati esegue quel comando, e poi il comando più esterno: serve, cioè, a lanciare un comando nel comando.

Detto questo, ormai tutto risulta semplice: esegue il comando cp copiando il file esistente, $oldfile, con il nuovo nome, che sarà il nome stesso senza estensione vecchia (comando basename), con agganciata l’estensione nuova .html (fare attenzione a non mettere spazi prima di .html

done

chiude il ciclo for.

Riassumo

Volendo formattare meglio lo script:
for oldfile in *.txt;
do
cp "$oldfile" "`basename "$oldfile" .txt`".html;
done

In questo modo il codice risulta più leggibile (ma non scrivetelo così andando a capo, otterreste solo errori :-) ).

Se sono stato abbastanza chiaro, dovreste riuscire, modificando di poco il comando, a rinominare gruppi di file cambiandone la parte finale (in genere l’estenzione) o magari aggiungendo dei caratteri all’inizio. Per sostituire dei caratteri con degli altri, ovunque si trovino, la faccenda si complica un po’… magari lo vediamo in un altro POST.

ispirato da DebianAdmin.com

  1. #1 di marco il 15 luglio 2010 - 23:09

    scusate una informazione, sono neofita della bash..

    avrei bisogno di creare uno script per zippare più file contemporaneamente in modo che ogni file generi il proprio corrispondente zippato.

    purtroppo ho un problema con gli spazi all’interno dei nomi

    il codice che ho provato è:

    for i in “$(ls *.avi)”; do zip -9 -q $(basename “$i” .avi).zip “$i”; done

    ma viene generato un file temporaneo da 4kb e rimane tutto immobile..possibile che l’abbia mandato in loop?

    grazie mille in anticipo e grandi per la dritta delle virgolette al posto giusto ;)

  2. #2 di Lorex il 11 gennaio 2010 - 18:11

    C’è uno script hce cambia l’estenzione? Magari uno script per VBS?

  3. #4 di fero il 13 giugno 2009 - 00:53

    Il tuo script è molto interessante, solo che potrebbe fare dei danni assurdi nel caso ci sia uno spazio nel nome del file originale !

    …cioè non proprio dei danni assurdi… ti può dare errore nella copia o nell’esecuzione di basename :)

    La versione corretta è con le ” ” al punto giusto !

    for i in *.txt; do cp “$i” “`basename “$i” .txt`.html”; done

    • #5 di bubbakk il 13 giugno 2009 - 11:59

      Grazie mille per avermi fatto notare l’errore. Effettivamente, con nomi dei file con gli spazi lo script genera un errore e non copia quei singoli file (il comando genera effettivamente un errore di comando con argomenti errati).
      Ho corretto il codice.

(non verrà pubblicata)