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_number
habí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
--progress
opción muestra:run_\#003/
etc.con (supongo) que el número que coincide con el entero estásp.run_number
relleno 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 l
obtengo:
run_$
run_\001$
run_\002$
run_\003$
run_\004$
run_\005$
run_\006$
run_\a$
run_\b$
run_\t$
run_$
No puedo acceder a cd
las 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
^A
es^
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
rename
utilidad perl (akaprename
ofile-rename
) para cambiar el nombre de los directorios.NOTA: Esto no debe confundirse con
rename
fromutil-linux
ni 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^A
convierte en 1, se^B
convierte en 2, etc.los
-n
opción es que una ejecución en seco muestre quérename
haría si lo dejara. Elimínelo (o reemplácelo con-v
una salida detallada) para cambiar el nombre.El
e
modificador en las/LHS/RHS/eg
operación hace que perl ejecute el RHS (el reemplazo) como código perl, y los$1
datos 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_number
su 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_number
pudiera 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 unpack
para 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
-n
opció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.2
de manera segura su I'mnot la misma funciónrename
utilidad.util-linux
'srename
es muy diferente, mucho menos capaz, y las opciones de línea de comando son incompatibles. Si está ejecutando Debian o similar, intente instalar elfile-rename
paquete. de lo contrario, instale el paquete apropiado para su distribución. puede que ya esté instalado, intente ejecutarloprename
ofile-rename
no 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_number
fue1
, 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),^A
son 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_?
-ls
no 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
,\b
y\t
son 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, perocd
solo espera uno.Todos ellos, en cierto sentido ...
En Bash, puede usar las comillas
\000
y\x00
escapa 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
/--escape
y--quoting-style=
, o laQUOTING_STYLE
variable 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