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).
Right-click the file and click Properties. The image below shows that you can determine the size of the file or files you have highlighted from in the file properties window. In this example, the chrome. jpg file is 18.5 KB (19,032 bytes), and that the size on disk is 20.0 KB (20,480 bytes).
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
Or you can use GNU od
utility, e.g.:
od -tfD file.bin
0000000 0.123
0000010
Where -t
parameter specifies the output format for floating-point number (f
) followed by optional size specifier (F
for float, D
for double or L
for long double), in short -tfD
can be replaced by -e
or -F
. To print only value without address, -A n
can be specified.
od -f <filename>
That will dump your file as floats.
od
is a standard Linux tool, and it's what I use. The manpage reads:
od - dump files in octal and other formats
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With