Estaba resolviendo un desafío donde encontré un archivo de datos sin extensión de archivo. El file
comando muestra que es un data file (application/octet-stream)
. El hd
comando muestra GNP. en la ultima linea. Entonces, si revierto este archivo, obtendré el archivo de formato .PNG , busqué en todas partes pero no encontré una solución que explicara cómo revertir el contenido de un archivo binario.
11
En
zsh
(el único shell que puede manejar internamente datos binarios (a menos que desee considerar el enfoque de codificación base64 de ksh93 )):LC_ALL=C
: los caracteres son bytes$mapfile[file.gnp]
: contenido delfile.gnp
archivos::
: divide la cadena en sus componentes de bytesOa
:O
rder inverso ena
subíndice de matriz que matrizfuente
zsh
No es el único shell que puede manejar datos binarios.Aquí hay una forma de invertir un archivo binario usando
ksh93
. He dejado el código "suelto" para que sea más fácil de entender.fuente
read
anterior no debería leer nada, ya que se hace al final del archivo.strace
yksh93
parece que se comporta de manera muy extraña, donde busca en todo el lugar dentro del archivo y lee grandes cantidades en ese momento. Quizás una variante de github.com/att/ast/issues/15strace
el guión para ver a qué me refiero.ksh93
lee los archivos miles de veces. Por ejemplo, antes de leer el primer byte, busca 64KiB al final del archivo, lee 64KiB, luego busca antes del último byte y lee 1 byte y hace algo similar para cada byte. Tenga en cuenta que lo que puede hacer con esas cadenas codificadas en base64 es limitado, por lo que si lee más de un byte a la vez, será más difícil extraer los bytes individuales de eso.Con perl:
Prueba de rendimiento:
Resultado:
perl -0777 -F
la más lenta.xxd
es la más lenta.Nota: el tiempo de
diff
ejecución debe ser el mismo para todas las soluciones, ya que la salida debe ser la misma.fuente
perl
uno. En ese momento no me había dado cuenta de que tambiénreverse
podía invertir las cadenas, por lo que hacer esa división no tenía mucho sentido y su versión es mucho mejor.Intenté lo siguiente:
La idea es forzar 'tac' usando cualquier carácter como separador. Lo intenté en un archivo binario y parecía funcionar, pero cualquier confirmación sería apreciada.
La principal ventaja es que no carga el archivo en la memoria.
fuente
tac
8.28) cuando la entrada contiene caracteres de nueva línea.printf '1\n2' | tac -rs . | od -vAn -tc
salidas en\n 2 1
lugar de2 \n 1
. También necesitaríaLC_ALL=C
o.
podría coincidir con caracteres de varios bytes.LC_ALL=C tac -rs $'.\\|\n'
parece funcionar sin embargo.