GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo cambiar el nombre de forma masiva de archivos con codificación no válida o reemplazar de forma masiva caracteres codificados no válidos?

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 el find la salida está delimitada por nulos, por lo que podemos leerla con read -d '' en el file 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 llamados resume y ré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:

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. 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.


Linux
  1. Cómo cifrar archivos con gocryptfs en Linux

  2. Cómo convertir archivos a codificación UTF-8 en Linux

  3. Cómo cambiar el nombre de los archivos en Linux

  4. Cómo descomprimir archivos en Linux (con ejemplos)

  5. ¿Cómo cambio el nombre de los archivos con espacios usando el shell de Linux?

Cómo cambiar el nombre de un archivo (s) en Linux

Cómo sincronizar archivos con Unison en Linux

Cómo eliminar archivos con extensión específica en Linux

Cómo encontrar archivos con el comando fd en Linux

Cómo subir archivos con FileZilla

¿Cómo cambiar el nombre de todos los archivos con caracteres especiales y espacios en un directorio?