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:
-depthassicurerà che le directory siano ricorse in profondità, quindi possiamo "arrotolare" tutto dalla fine. Di solito,findattraversa in modo diverso (ma non in ampiezza).-print0garantisce ilfindl'output è delimitato da null, quindi possiamo leggerlo conread -d ''nelfilevariabile. 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
$futilizzando 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
$newesiste già nella directory$d(ad esempio, hai file denominatiresumeerésuménella stessa directory), emette un avviso. Non vuoi rinominarlo, perché, su alcuni sistemi,mv foo foocausa 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/Encodingmv 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.