kenorb kenorb - 7 months ago 18
Bash Question

How to print float value from binary file in shell?

I've binary file consisting double float (8 bytes) or just float (4 bytes) value which was generated in the following way:

$ python -c $'from struct import pack\nwith open("file.bin", "wb") as f: f.write(pack("<d", 0.123))'
$ xxd file.bin
00000000: b072 6891 ed7c bf3f .rh..|.?


which I could print it back from Python via:

$ python -c $'from struct import unpack\nwith open("file.bin", "rb") as f: print(unpack("<d", f.read(8)))'
(0.123,)


The same for 4-byte float, just change
<d
into
<f
(mentioned as
float.bin
later on).

How do I print that value from the shell script using cleaner way (without using Python)? Either using built-in tools (e.g.
printf
), or wide-used external tools (e.g.
xxd
,
dc
,
bc
,
od
,
hexdump
, etc.).




For example to print decimal values, I can use
xxd
(part of Vim), e.g. in Bash:


  • get the value of first byte:

    $ echo $((16#$(xxd -ps -s0 -l1 file.bin)))
    176


    For 2nd and forth bytes, increase
    -s
    .

  • get decimal value from all 8 bytes:

    $ echo $((16#$(xxd -ps -s0 -l8 file.bin)))
    -5732404399725297857



However I would like to print original floating value (
0.123
) on Unix-family system.
Ideally using some one-liner (to keep it simple as part of the script), so I can assign it into text variable or print the value on the screen.




I've tried to use
printf
(on the 4-byte float number to make it simpler), but it didn't work as expected:

$ xxd -p float.bin
6de7fb3d
$ printf "%.4f\n" 0x.$(xxd -p float.bin)
0.4293
$ printf "%.4f\n" 0x3dfbe76d
1039918957.0000
$ printf "%.4e\n" 0x3dfbe76d
1.0399e+09


where according to this on-line converter,
0x3dfbe76d
is the same as
0.123
, so the hex values are in reverse (what
xxd
actually gives).

Answer

This doesn't use Python and is a widely-used external tool, Perl.

perl -e "print pack('d>',0.123)" > file.bin

perl -e "print unpack('d>',<>)" < file.bin
0.123

Maybe you can use GNU od

od -tfD file.bin
0000000                    0.123
0000010
Comments