Traiter des données binaires à un bas niveau dans les scripts shell est généralement une mauvaise idée.
bashles variables ne peuvent pas contenir l'octet 0. zshest le seul shell qui peut stocker cet octet dans ses variables.
Dans tous les cas, les arguments de commande et les variables d'environnement ne peuvent pas contenir ces octets car ce sont des chaînes délimitées NUL passées à l' execveappel système.
Notez également que:
var=`cmd`
ou sa forme moderne:
var=$(cmd)
supprime tous les caractères de nouvelle ligne de fin de la sortie de cmd. Donc, si cette sortie binaire se termine par 0xa octets, elle sera altérée lorsqu'elle sera stockée dans $var.
Ici, vous devez stocker les données encodées, par exemple avec xxd -p.
hdr_988=$(head -c 988 < "$inputFile" | xxd -p)
printf '%s\n' "$hdr_988" | xxd -p -r > "$output_hdr"
Vous pouvez définir des fonctions d'assistance comme:
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 sortie n'est pas efficace en termes d'espace car elle code 1 octet en 2 octets, mais elle facilite les manipulations avec elle (concaténation, extraction de parties). base64est celui qui code 3 octets en 4, mais n'est pas aussi facile à utiliser.
Le ksh93shell a un format de codage intégré (utilise base64) que vous pouvez utiliser avec ses utilitaires readet printf/ print:
typeset -b var # marked as "binary"/"base64-encoded"
IFS= read -rn 988 var < input
printf %B var > output
Maintenant, s'il n'y a pas de transit via des variables shell ou env, ou des arguments de commande, vous devriez être OK tant que les utilitaires que vous utilisez peuvent gérer n'importe quelle valeur d'octet. Mais notez que pour les utilitaires de texte, la plupart des implémentations non GNU ne peuvent pas gérer les octets NUL, et vous voudrez corriger les paramètres régionaux en C pour éviter les problèmes avec les caractères multi-octets. Le dernier caractère n'étant pas un caractère de nouvelle ligne peut également provoquer des problèmes ainsi que des lignes très longues (séquences d'octets entre deux octets 0xa qui sont plus longs LINE_MAX).
head -coù il est disponible devrait être OK ici, car il est censé fonctionner avec des octets, et n'a aucune raison de traiter les données comme du texte. Donc
head -c 988 < input > output
ça devrait être bon. En pratique, au moins les implémentations intégrées GNU, FreeBSD et ksh93 sont OK. POSIX ne spécifie pas l' -coption, mais indique qu'il headdevrait prendre en charge les lignes de n'importe quelle longueur (sans s'y limiter LINE_MAX)
Avec zsh:
IFS= read -rk988 -u0 var < input &&
print -rn -- $var > output
Ou:
var=$(head -c 988 < input && echo .) && var=${var%.}
print -rn -- $var > output
Même dans zsh, s'il $varcontient des octets NUL, vous pouvez le passer comme argument aux commandes zshinternes (comme printci-dessus) ou aux fonctions, mais pas comme arguments aux exécutables, car les arguments passés aux exécutables sont des chaînes délimitées par NUL, c'est une limitation du noyau, indépendante du shell.
ddpour copier des octets individuels (en le définissantcountsur1). Je ne suis pas sûr de les stocker, cependant.