Tratar con datos binarios a un nivel bajo en scripts de shell es generalmente una mala idea.
bashlas variables no pueden contener el byte 0. zshes el único shell que puede almacenar ese byte en sus variables.
En cualquier caso, los argumentos de comando y las variables de entorno no pueden contener esos bytes, ya que son cadenas delimitadas por NUL que se pasan a la execvellamada del sistema.
También tenga en cuenta que:
var=`cmd`
o su forma moderna:
var=$(cmd)
elimina todos los caracteres de nueva línea finales de la salida de cmd. Entonces, si esa salida binaria termina en 0xa bytes, se destruirá cuando se almacene en $var.
Aquí, necesitaría almacenar los datos codificados, por ejemplo con xxd -p.
hdr_988=$(head -c 988 < "$inputFile" | xxd -p)
printf '%s\n' "$hdr_988" | xxd -p -r > "$output_hdr"
Podría definir funciones auxiliares como:
encode() {
eval "$1"='$(
shift
"$@" | xxd -p -c 0x7fffffff
exit "${PIPESTATUS[0]}")'
}
decode() {
printf %s "$1" | xxd -p -r
}
encode var cat /bin/ls &&
decode "$var" | cmp - /bin/ls && echo OK
xxd -pla salida no es eficiente en cuanto al espacio, ya que codifica 1 byte en 2 bytes, pero hace que sea más fácil hacer manipulaciones con ella (concatenación, extracción de partes). base64es uno que codifica 3 bytes en 4, pero no es tan fácil trabajar con él.
El ksh93shell tiene un formato de codificación incorporado (usos base64) que puede usar con sus ready printf/ printutilidades:
typeset -b var # marked as "binary"/"base64-encoded"
IFS= read -rn 988 var < input
printf %B var > output
Ahora, si no hay tránsito a través de variables de shell o env, o argumentos de comando, debe estar bien siempre que las utilidades que use puedan manejar cualquier valor de byte. Pero tenga en cuenta que para las utilidades de texto, la mayoría de las implementaciones que no son GNU no pueden manejar bytes NUL, y querrá arreglar la configuración regional en C para evitar problemas con los caracteres de varios bytes. El último carácter que no es un carácter de nueva línea también puede causar problemas, así como líneas muy largas (secuencias de bytes entre dos bytes 0xa más largos LINE_MAX).
head -cdonde esté disponible debería estar bien aquí, ya que está destinado a trabajar con bytes y no tiene ninguna razón para tratar los datos como texto. Entonces
head -c 988 < input > output
debería estar bien. En la práctica, al menos las implementaciones incorporadas de GNU, FreeBSD y ksh93 están bien. POSIX no especifica la -copción, pero dice que headdebería admitir líneas de cualquier longitud (no limitado a LINE_MAX)
Con zsh:
IFS= read -rk988 -u0 var < input &&
print -rn -- $var > output
O:
var=$(head -c 988 < input && echo .) && var=${var%.}
print -rn -- $var > output
Incluso en el zshcaso de que $varcontenga bytes NUL, puede pasarlo como argumento a las zshfunciones incorporadas (como printarriba) o funciones, pero no como argumentos a los ejecutables, ya que los argumentos pasados a los ejecutables son cadenas delimitadas por NUL, eso es una limitación del núcleo, independiente del shell.
ddpara copiar bytes individuales (estableciendo sucounten1). Sin embargo, no estoy seguro de almacenarlos.