So che non è esattamente quello che volevi, ma se conosci la codifica originale, forse puoi usare convmv
per modificare la codifica in UTF-8, che dovrebbe risolvere la maggior parte dei problemi.
Questo ha funzionato per me su una cartella con alcuni nomi di file polacchi con codifica non valida:
convmv -f cp1250 -t utf8 -r .
Nota che questo comando in realtà non rinomina nulla; aggiungi --notest
opzione per rinominare veramente i file.
Incontrerai qualche problema se vorrai rinominare i file e directory contemporaneamente. Rinominare solo un file è abbastanza facile. Ma vuoi assicurarti che anche le directory vengano rinominate. Non puoi semplicemente mv Motörhead/Encöding Motorhead/Encoding
dal Motorhead
non esisterà al momento della chiamata.
Quindi, abbiamo bisogno di una prima traversata approfondita di tutti i file e le cartelle, quindi rinominare solo il file o la cartella corrente. Quanto segue funziona con GNU find
e Bash 4.2.42 sul mio OS X.
#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
d="$( dirname "$file" )"
f="$( basename "$file" )"
new="${f//[^a-zA-Z0-9\/\._\-]/}"
if [ "$f" != "$new" ] # if equal, name is already clean, so leave alone
then
if [ -e "$d/$new" ]
then
echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
ls -ld "$d/$new" "$d/$f"
else
echo mv "$file" "$d/$new" # remove "echo" to actually rename things
fi
fi
done
Puoi modificare la regex usando new="${f//[\\\/\:\*\?\"<>|]/}"
se vuoi sostituire qualcosa che Windows non è in grado di gestire.
Salva questo script come rename.sh
, rendilo eseguibile con chmod +x rename.sh
. Quindi, chiamalo come rename.sh /some/path
.
Assicurati di risolvere eventuali collisioni di nomi di file ("Notice
” annunci).
Se sei assolutamente sicuro fa le giuste sostituzioni, rimuovi il echo
dallo script per rinominare effettivamente le cose invece di limitarsi a stampare quello che fa.
Per sicurezza, ti consiglio di testarlo prima su un piccolo sottoinsieme di file.
Spiegazione delle opzioni
Per spiegare cosa succede qui:
-depth
assicurerà che le directory siano ricorse in profondità, quindi possiamo "arrotolare" tutto dalla fine. Di solito,find
attraversa in modo diverso (ma non in ampiezza).-print0
garantisce ilfind
l'output è delimitato da null, quindi possiamo leggerlo conread -d ''
nelfile
variabile. Ciò ci aiuta a gestire tutti i tipi di nomi di file strani, inclusi quelli con spazi e persino le nuove righe.- Otteniamo la directory del file con
dirname
. Non dimenticare di citare sempre correttamente le tue variabili, altrimenti qualsiasi percorso con spazi o caratteri glob interromperebbe questo script. - Otteniamo il nome effettivo del file (o il nome della directory) con
basename
. - Quindi, rimuoviamo qualsiasi carattere non valido da
$f
utilizzando le capacità di sostituzione delle stringhe di Bash. Non valido significa qualsiasi cosa che non sia una lettera minuscola o maiuscola, una cifra, una barra (\/
), un punto (\.
), un trattino basso o un trattino meno. - Se
$f
è già pulito (il nome pulito è identico al nome corrente), saltalo. - Se
$new
esiste già nella directory$d
(ad esempio, hai file denominatiresume
erésumé
nella stessa directory), emette un avviso. Non vuoi rinominarlo, perché, su alcuni sistemi,mv foo foo
causa un problema. Altrimenti, - Alla fine rinominiamo il file originale (o la directory) con il suo nuovo nome
Poiché questo agirà solo sulla gerarchia più profonda, rinominando Motörhead/Encöding
a Motorhead/Encoding
avviene in due fasi:
mv Motörhead/Encöding Motörhead/Encoding
mv Motörhead Motorhead
Ciò garantisce che tutte le sostituzioni vengano eseguite nell'ordine corretto.
File di esempio ed esecuzione di test
Supponiamo alcuni file in una cartella di base chiamata test
:
test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule
Ecco l'output di un'esecuzione in modalità debug (con echo
davanti al mv
), ovvero i comandi che verrebbero chiamati e gli avvisi di collisione:
mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r-- … … test/work/resume
-rw-r—r-- … … test/work/résumé
Notare l'assenza di messaggi per with-hyphen.txt
, schedule
e test
stesso.