Sim, você pode fazer isso no pipeline sem ter que ler o arquivo inteiro.
Este primeiro fragmento de script ilustra o mecanismo pelo qual vamos interceptar e inspecionar o cabeçalho e passá-lo adiante. Observe que imprimimos o cabeçalho para stderr (> & 2), mas ele continua aparecendo na saída:
$ echo 0123456789ABCDEF |
(
HEADER=$(dd bs=1 count=4);
printf 'HEADER:%s\n' "$HEADER" >&2;
printf '%s\n' "$HEADER";
cat
)
4+0 records in
4+0 records out
4 bytes (4 B) copied, 8.4293e-05 s, 47.5 kB/s
HEADER:0123
0123456789ABCDEF
$
A chave está usando o dd
do utilitário de conversão de arquivos com um tamanho de bloco pequeno bs=1
.
Expandindo isso, esta é uma solução funcional. Usaremos um arquivo temporário para armazenar o cabeçalho binário. Se ele não vir um dos dois cabeçalhos de 4 bytes, não fará nada:
#!/bin/sh
trap "rm -f /tmp/$$; exit 1" 1 2 3 15
# grab the 1st 4 bytes off the input stream,
# store them in a file, convert to ascii,
# and store in variable:
HEADER=$(
dd bs=1 count=4 2>/dev/null |
tee /tmp/$$ |
od -t x1 |
sed '
s/^00* //
s/ //g
q
'
)
case "$HEADER" in
1f8b0800)
UNCOMPRESS='gzip -d -fc'
;;
425a6839)
UNCOMPRESS='bzip2 -d -fc'
;;
*)
echo >&2 "$0: unknown stream type for header '$HEADER'"
exit 2
;;
esac
echo >&2 "$0: File header is '$HEADER' using '$UNCOMPRESS' on stream."
cat /tmp/$$ - | $UNCOMPRESS
rm /tmp/$$