Lo siento si esto tiene una respuesta en otra parte, no tengo idea de cómo buscar mi problema.
Estaba ejecutando algunas simulaciones en un servidor HPC redhat linux, y mi código para manejar la estructura de carpetas para guardar la salida tenía un error desafortunado. Mi código matlab para crear la carpeta fue:
folder = [sp.saveLocation, 'run_', sp.run_number, '/'];
donde sp.run_numberhabía un número entero Olvidé convertirlo en una cadena, pero por alguna razón la ejecución mkdir(folder);(en matlab) todavía tuvo éxito. De hecho, las simulaciones se ejecutaron sin problemas y los datos se guardaron en el directorio correspondiente.
Ahora, cuando se consulta / imprime la estructura de carpetas, aparece la siguiente situación:
- Cuando intento tabular autocompletar:
run_ run_^A/ run_^B/ run_^C/ run_^D/ run_^E/ run_^F/ run_^G/ run_^H/ run_^I/ - Cuando uso
ls:run_ run_? run_? run_? run_? run_? run_? run_? run_? run_? run_?. - Cuando transfiero a mi Mac usando rsync, la
--progressopción muestra:run_\#003/etc.con (supongo) que el número que coincide con el entero estásp.run_numberrelleno con tres dígitos, por lo que la décima ejecución esrun_\#010/ - Cuando veo las carpetas en el buscador veo
run_ run_ run_ run_ run_ run_ run_ run_ run_ run_? - Mirando esta pregunta y usando el comando
ls | LC_ALL=C sed -n lobtengo:
run_$
run_\001$
run_\002$
run_\003$
run_\004$
run_\005$
run_\006$
run_\a$
run_\b$
run_\t$
run_$
No puedo acceder a cdlas carpetas con ninguna de estas representaciones.
Tengo miles de estas carpetas, así que tendré que arreglar esto con un script. ¿Cuál de estas opciones es la representación correcta de la carpeta? ¿Cómo puedo referirme programáticamente a estas carpetas para cambiarles el nombre con un nombre formateado correctamente usando un script bash? Y supongo que por curiosidad, ¿cómo diablos sucedió esto en primer lugar?
fuente

^Aes^seguido literalmenteA, sino Ctrl-A (puede escribirlo usando Ctrl-V Ctrl-A ya que Ctrl-A es generalmente un acceso directo para el shell).run_y tengo que escribir algo/. Cualquier otro carácter es válido, incluidos los caracteres de control. No sé qué habría hecho matlab si sp.run_number fuera 0 (probablemente abortar con un error o producirrun_, ya que el byte NUL terminaría la cadena del nombre del directorio). Por supuesto, esto también sería problemático para los valores de 16 bits (o superiores) que tenían un byte NUL en ellos, y también variaría de acuerdo con la endianidad del sistema que ejecuta matlab.Respuestas:
Puede usar la
renameutilidad perl (akaprenameofile-rename) para cambiar el nombre de los directorios.NOTA: Esto no debe confundirse con
renamefromutil-linuxni con ninguna otra versión.Esto utiliza la
ord()función de perl para reemplazar cada carácter de control en el nombre del archivo con el número ordinal para ese carácter. por ejemplo, se^Aconvierte en 1, se^Bconvierte en 2, etc.los
-nopción es que una ejecución en seco muestre quérenameharía si lo dejara. Elimínelo (o reemplácelo con-vuna salida detallada) para cambiar el nombre.El
emodificador en las/LHS/RHS/egoperación hace que perl ejecute el RHS (el reemplazo) como código perl, y los$1datos coincidentes (el carácter de control) del LHS.Si desea números rellenados con ceros en los nombres de archivo, puede combinarlos
ord()consprintf(). p.ejLos ejemplos anteriores funcionan si y solo si
sp.run_numbersu script matlab estaba en el rango de 0..26 (por lo que produjo caracteres de control en los nombres de directorio).Para tratar CUALQUIER carácter de 1 byte (es decir, de 0..255), usaría:
Si
sp.run_numberpudiera ser> 255, tendrías que usar perl'sunpack()función lugar deord(). No sé exactamente cómo matlab genera un int no convertido en una cadena, por lo que tendrá que experimentar. Verperldoc -f unpackpara más detalles.por ejemplo, lo siguiente descomprimirá los valores sin signo de 8 y 16 bits y los pondrá a cero a 5 dígitos de ancho:
fuente
-nopción, pero me está diciendo su una opción no válida - la información de versión me darename from util-linux 2.23.2de manera segura su I'mnot la misma funciónrenameutilidad.util-linux'srenamees muy diferente, mucho menos capaz, y las opciones de línea de comando son incompatibles. Si está ejecutando Debian o similar, intente instalar elfile-renamepaquete. de lo contrario, instale el paquete apropiado para su distribución. puede que ya esté instalado, intente ejecutarloprenameofile-renameno solorename.Entonces, parecería que
mkdir([...])en Matlab concatena los miembros de la matriz para construir el nombre de archivo como una cadena. Pero le diste un número, y los números son lo que realmente son los personajes de una computadora. Entonces, cuandosp.run_numberfue1, te dio el personaje con valor1, y luego el personaje con valor2, etc.Esos son caracteres de control, no tienen símbolos imprimibles, e imprimirlos en un terminal tendría otras consecuencias. Entonces, en cambio, a menudo están representados por diferentes tipos de escapes:
\001(octal),\x01(hex),^Ason todas representaciones comunes para el personaje con valor1. El carácter con valor cero es un poco diferente, es el byte NUL que se usa para marcar el final de una cadena en C y en las llamadas al sistema Unix.Si fue más alto que 31, comenzaría a ver caracteres imprimibles, 32 es espacio (aunque no muy visible), 33 =
!, 34 ="etc.Entonces,
run_ run_^A/ run_^B/- El primerorun_corresponde al que tiene un byte cero, la cadena termina allí. Los demás muestran que a su shell le gusta usar mostrar los códigos de control^A. La notación también insinúa el hecho de que el carácter con valor numérico 1 se puede ingresar como Ctrl-A, aunque debe decirle al shell que interprete no como un carácter de control, sino como un literal, Ctrl-V Ctrl-Adebe hacerlo al menos en Bash.ls:
run_ run_? run_?-lsno le gusta imprimir caracteres no imprimibles en el terminal, los reemplaza con signos de interrogación.rsync:
run_\#003/ese es nuevo para mí, pero la idea es la misma, la barra invertida marca un escape y el resto es el valor numérico del personaje. Me parece que el número aquí está en octal, como en el más común\003.usando el comando
ls | LC_ALL=C sed -n l...run_\006$run_\a$run_\b$run_\t$-\a,\by\tson C escapes para alarma (campana), retroceso y tabulación, respectivamente. Tienen los valores numéricos 7, 8 y 9, por lo que debe quedar claro por qué vienen después\006. Usar esos escapes en C es otra forma de marcar los caracteres de control. Los signos de dólar finales marcan el final de la línea.En cuanto a
cd, suponiendo que mis suposiciones sean correctas,cd run_debería ir a ese único directorio sin un carácter final extraño, ycd run_?debería dar un error ya que el signo de interrogación es un carácter global que coincide con cualquier carácter individual, y hay varios nombres de archivo coincidentes, perocdsolo espera uno.Todos ellos, en cierto sentido ...
En Bash, puede usar las comillas
\000y\x00escapa dentro de las$'...'comillas para representar los caracteres especiales, por lo que$'run_\033(octal) o$'run_\x1b'corresponder al directorio con el valor de carácter 27 (que resulta ser ESC). (No creo que Bash admita escapes con números decimales).La respuesta de cas tiene un guión para cambiarles el nombre, así que no iré allí.
fuente
ls, hay algunas opciones de comillas que incluyen-b/--escapey--quoting-style=, o laQUOTING_STYLEvariable de entorno, para controlar cómo se muestran los caracteres que no se imprimen. Sin embargo, no creo que haya una opción para hacer que prefiera los escapes octales a las versiones de los personajes.Lo más fácil sería crear el nombre de archivo incorrecto y el nombre de archivo correcto en el mismo entorno donde ocurrió el error, y luego simplemente mover / cambiar el nombre de las carpetas a los nombres correctos.
Para evitar colisiones entre nombres existentes, utilice mejor otra carpeta de destino.
Si es posible, preferiría arreglar el script y simplemente ejecutarlo nuevamente; arreglar algunos errores extraños post mortem probablemente cuesta más y puede introducir nuevos problemas.
¡Buena suerte!
fuente