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).
od
(part ofcoreutils
) is even shorter, this works great, thank you. Here is trimmed version:od -tfD file.bin | awk '{print $2}' | xargs
. – Verniavernice