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).
This doesn't use Python and is a widely-used external tool, Perl.
Or you can use GNU
od
utility, e.g.:Where
-t
parameter specifies the output format for floating-point number (f
) followed by optional size specifier (F
for float,D
for double orL
for long double), in short-tfD
can be replaced by-e
or-F
. To print only value without address,-A n
can be specified.You may wish to consider some of the mentioned tools such as
bc
which can be used in arithmetic operations and comparisons - eg:Additional formatting for related numbers and types such as zero may be required; as addressed in some other postings eg: How to show zero before decimal point in bc?
That will dump your file as floats.
od
is a standard Linux tool, and it's what I use. The manpage reads:As a oneliner