Sé que no es exactamente lo que querías, pero si conoces la codificación original, tal vez puedas usar convmv
para cambiar la codificación a UTF-8, lo que debería solucionar la mayoría de los problemas.
Esto funcionó para mí en una carpeta con algunos nombres de archivo polacos codificados no válidos:
convmv -f cp1250 -t utf8 -r .
Tenga en cuenta que este comando en realidad no cambia el nombre de nada; añadir --notest
opción para realmente cambiar el nombre de los archivos.
Tendrá algunos problemas si desea cambiar el nombre de los archivos y directorios al mismo tiempo. Renombrar solo un archivo es bastante fácil. Pero desea asegurarse de que los directorios también cambien de nombre. No puedes simplemente mv Motörhead/Encöding Motorhead/Encoding
desde Motorhead
no existirá en el momento de la llamada.
Por lo tanto, necesitamos un recorrido en profundidad de todos los archivos y carpetas, y luego cambiar el nombre del archivo o carpeta actual solamente. Lo siguiente funciona con GNU find
y Bash 4.2.42 en mi 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
Puede cambiar la expresión regular usando new="${f//[\\\/\:\*\?\"<>|]/}"
si desea reemplazar algo que Windows no puede manejar.
Guarde este script como rename.sh
, hazlo ejecutable con chmod +x rename.sh
. Luego, llámalo como rename.sh /some/path
.
Asegúrese de resolver cualquier colisión de nombres de archivos ("Notice
” anuncios).
Si está absolutamente seguro hace los reemplazos correctos, elimine el echo
del script para cambiar el nombre de las cosas en lugar de simplemente imprimir lo que hace.
Para estar seguro, recomendaría probar esto primero en un pequeño subconjunto de archivos.
Opciones explicadas
Para explicar lo que sucede aquí:
-depth
se asegurará de que los directorios se repitan primero en profundidad, por lo que podemos "resumir" todo desde el final. Por lo general,find
atraviesa de manera diferente (pero no en anchura).-print0
asegura elfind
la salida está delimitada por nulos, por lo que podemos leerla conread -d ''
en elfile
variable. Hacerlo nos ayuda a lidiar con todo tipo de nombres de archivo extraños, incluidos los que tienen espacios e incluso líneas nuevas.- Obtendremos el directorio del archivo con
dirname
. No olvide citar siempre sus variables correctamente, de lo contrario, cualquier ruta con espacios o caracteres globulosos rompería este script. - Obtendremos el nombre de archivo real (o nombre de directorio) con
basename
. - Luego, eliminamos cualquier carácter no válido de
$f
usando las capacidades de reemplazo de cadenas de Bash. Inválido significa cualquier cosa que no sea una letra minúscula o mayúscula, un dígito, una barra oblicua (\/
), un punto (\.
), un guión bajo o un guión menos. - Si
$f
ya está limpio (el nombre limpio es idéntico al nombre actual), sáltelo. - Si
$new
ya existe en el directorio$d
(por ejemplo, tiene archivos llamadosresume
yrésumé
en el mismo directorio), emita una advertencia. No desea cambiarle el nombre porque, en algunos sistemas,mv foo foo
causa un problema. De lo contrario, - Finalmente cambiamos el nombre del archivo original (o directorio) a su nuevo nombre
Dado que esto solo actuará en la jerarquía más profunda, renombrando Motörhead/Encöding
a Motorhead/Encoding
se realiza en dos pasos:
mv Motörhead/Encöding Motörhead/Encoding
mv Motörhead Motorhead
Esto garantiza que todos los reemplazos se realicen en el orden correcto.
Archivos de ejemplo y ejecución de prueba
Supongamos algunos archivos en una carpeta base llamada 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
Aquí está el resultado de una ejecución en modo de depuración (con el echo
delante del mv
), es decir, los comandos que se llamarían y las advertencias de colisión:
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é
Observe la ausencia de mensajes para with-hyphen.txt
, schedule
y test
mismo.