Tengo un montón de directorios y subdirectorios que contienen archivos con caracteres especiales, como este archivo:
robbie@phil:~$ ls test�sktest.txt
test?sktest.txt
Find revela una secuencia de escape:
robbie@phil:~$ find test�sktest.txt -ls
424512 4000 -rwxr--r-x 1 robbie robbie 4091743 Jan 26 00:34 test\323sktest.txt
La única razón por la que incluso puedo escribir sus nombres en la consola es porque se completó la pestaña. Esto también significa que puedo cambiarles el nombre manualmente (y quitarle el carácter especial).
He configurado LC_ALL en UTF-8, lo que no parece ayudar (tampoco en un nuevo shell):
robbie@phil:~$ echo $LC_ALL
en_US.UTF-8
Me estoy conectando a la máquina usando ssh desde mi mac. Es una instalación de Ubuntu:
robbie@phil:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=7.10
DISTRIB_CODENAME=gutsy
DISTRIB_DESCRIPTION="Ubuntu 7.10"
Shell es Bash, TERM se establece en xterm-color.
Estos archivos han estado allí durante bastante tiempo y no se han creado con esa instalación de Ubuntu. Así que no sé cuál era la configuración de codificación del sistema.
He intentado cosas como:
find . -type f -ls | sed 's/[^a-zA-Z0-9]//g'
Pero no puedo encontrar una solución que haga todo lo que quiero:
- Identifique todos los archivos que tienen caracteres que no se pueden mostrar (lo anterior ignora demasiado)
- Para todos esos archivos en un árbol de directorios (recursivamente), ejecute mv oldname newname
- Opcionalmente, la capacidad de transcribir caracteres especiales como ä a a (no es obligatorio, pero sería increíble)
O
- Muestra correctamente todos estos archivos (y no hay errores en las aplicaciones al intentar abrirlos)
Tengo partes y piezas, como iterar sobre todos los archivos y moverlos, pero identificar los archivos y formatearlos correctamente para el comando mv parece ser la parte difícil.
Cualquier información adicional sobre por qué no se muestran correctamente o cómo "adivinar" la codificación correcta también es bienvenida. (He intentado convmv pero no parece hacer exactamente lo que quiero: http://j3e.de/linux/convmv/ )
Respuestas:
Supongo que ves este
�
carácter no válido porque el nombre contiene una secuencia de bytes que no es válida UTF-8. Los nombres de archivo en los sistemas de archivos Unix típicos (incluido el suyo) son cadenas de bytes, y depende de las aplicaciones decidir qué codificación usar. Hoy en día, existe una tendencia a usar UTF-8, pero no es universal, especialmente en entornos locales que nunca podrían vivir con ASCII simple y que han estado utilizando otras codificaciones desde antes de que UTF-8 existiera.Intente
LC_CTYPE=en_US.iso88591 ls
ver si el nombre del archivo tiene sentido en ISO-8859-1 (latin-1). Si no es así, intente con otras configuraciones regionales. Tenga en cuenta que aquí soloLC_CTYPE
importa la configuración regional.En una configuración regional UTF-8, el siguiente comando le mostrará todos los archivos cuyo nombre no sea válido UTF-8:
Puede verificar si tienen más sentido en otro entorno local con recode o iconv :
Una vez que haya determinado que un grupo de nombres de archivos están en una determinada codificación (por ejemplo, latin1), una forma de cambiarles el nombre es
Utiliza el comando perl rename disponible en Debian y Ubuntu. Puede pasarlo
-n
para mostrar lo que estaría haciendo sin cambiar el nombre de los archivos.fuente
grep [^[:print:]]
de buscar caracteres no imprimibles. Pero acabo de probar con GNU grep y no se captan secuencias UTF-8 no válidas[^[:print:]]
(lo que tiene sentido ya que no son caracteres no imprimibles, no son caracteres en absoluto). He editado mi publicación con una forma más larga de líneas grepping con secuencias utf8 no válidas. Tenga en cuenta que también he fijado la dirección de larecode
yiconv
ejemplos.Sé que esta es una vieja pregunta, pero he estado buscando toda la noche una solución similar. Encontré algunos consejos útiles, pero no hicieron exactamente lo que necesitaba, así que tuve que mezclar y combinar algunos para obtener el resultado correcto que estaba buscando.
simplemente para eliminar caracteres especiales y reemplazarlos con un punto (.)
para usar en un cronjob hice lo siguiente para ejecutar cada minuto
Espero que alguien encuentre esto útil ya que me ha alegrado el día :)
fuente
`…`
a$(…)
: vea esto , esto y esto . (2) Siempre debe citar sus referencias de variables de shell (por ejemplo,"$f"
) a menos que tenga una buena razón para no hacerlo, y esté seguro de saber lo que está haciendo. Esto se aplica incluso aecho "$f" | sed …
. También se aplica a toda la$(…)
(o`…`
) expresión; es decir,mv "$f" "$(echo "$f" | sed "…")"
. ... (Continúa)mv
--
"$f" …
-
Ahora, cuando sepa qué codificación se usa para los nombres de archivo en el extremo remoto ("latin1", según los comentarios a la primera respuesta), también podría seguir la segunda forma : ejecute un termninal local y ssh en tal forma en que los nombres de archivos remotos se muestran correctamente (en lugar de la primera forma: renómbrelos) .
Como yo , podría iniciar un terminal localmente que funcionaría en esa codificación especial, tal vez, de esta manera:
LC_ALL = en_US.latin1 xvt &
xvt
representa su programa de terminal.Tal vez, la configuración regional existente se llama
en_US.iso88591
, y noen_US.latin1
, como supuse.fuente
Esto no cumple con los requisitos masivos, pero acabo de tener un problema similar en el que tenía varias versiones de un archivo con nombres similares que diferían solo por un solo personaje extraño. Desafortunadamente, esto significaba que no podía renombrar a los delincuentes usando el truco comodín que suelo usar.
Al final utilicé Filezilla para conectarme como un cliente SFTP, busqué los archivos y les cambié el nombre usando la GUI. Filezilla manejó los caracteres poco fiables bastante bien.
fuente