Often we need to deal with binary data. For instance, data from the network or the header of an image file are in binary format. If we print that out to the stdout, it shows some garbled characters, which are very difficult to understand.
In an earlier tutorial, we’ve seen how to create a hex dump of a file.
In this tutorial, we’ll see different ways to convert binary data to hexadecimal format.
2. Sampling Binary Data
Image files are a good source for binary data. For instance, the image metadata is stored in the file header in a binary format.
Let’s sample the contents of an image file header:
$ head -c 8 Image1.png �PNG
Here, we’ve used the head command to read the first eight bytes from the file. And we can see that it didn’t print the data properly.
However, in Linux, we have various tools to convert the binary data to hexadecimal for easier reading. Let’s look at some of them.
3. Using the hexdump Command
The hexdump command is the first command that comes to mind when we convert binary data to hexadecimal format. It helps us to print the result in different ways.
Let’s look at an example:
$ head -c 8 ~/Pictures/Image1.png | hexdump 0000000 5089 474e 0a0d 0a1a 0000008
After extracting the bytes from an image file, we’ve piped it to the hexdump command. And it printed the hexadecimal values correctly. We’ve used the hexdump command without any options.
3.1. Print ASCII Values
Typically, we would like to see the ASCII value of each byte. Having that side by side, we’ll be able to recognize the contents easily.
Let’s take a look at how we can do this:
$ head -c 8 ~/Pictures/Image1.png | hexdump -C 00000000 89 50 4e 47 0d 0a 1a 0a |.PNG....| 00000008
We’ve used the -C option to print the ASCII values. From the ASCII values, we could quickly identify it as a PNG file.
3.2. Formatting Output
The hexdump command provides a -e option, which can be used to format the output in different ways as we need.
Firstly, let’s start by printing just the hexadecimal values:
$ head -c 8 ~/Pictures/Image1.png | hexdump -e '8/1 "%02X " "\n"' 89 50 4E 47 0D 0A 1A 0A
Here, we passed a format string along with the -e option.
Let’s look at the different parameters in it:
- 8/1: prints 8 bytes in a line and 1 byte at a time
- ‘%02X ‘: prints in hexadecimal format with two digits having leading zeros
- \n: prints a newline as a separator in the end
Secondly, let’s add an address field for this:
$ head -c 8 ~/Pictures/Image1.png | hexdump -e '"%04_ax -> " 4/1 "%02X " "\n"' 0000 -> 89 50 4E 47 0004 -> 0D 0A 1A 0A
We’ve used the _ax option to add the address field. Prefixing %04 to it, we’ve specified the width of that field to be 4 digits with leading zeros. Finally, we’ve used the -> symbol as a separator.
Finally, let’s check how can we add the ASCII format:
$ head -c 8 ~/Pictures/Image1.png | hexdump -e '"%04_ax -> " 4/1 "%02X "' -e '" |" 4/1 " %_p" " |\n"' 0000 -> 89 50 4E 47 | . P N G | 0004 -> 0D 0A 1A 0A | . . . . |
Here, we’ve used a second -e option to print the ASCII format. We’ve used the _p option to print the ASCII values. Also, we used the | symbol as the separator.
4. Using the xxd Command
The xxd command creates a hex dump from any binary data. It also helps to format the output in the way we want.
Let’s take a look:
$ head -c 8 Image1.png | xxd 00000000: 8950 4e47 0d0a 1a0a .PNG....
Here, we read binary data from the image file. Then that is passed to the xxd command. We’ve used the xxd without any options. And it has printed the binary data in hex and ASCII format.
4.1. Formatting the Output
Default output may not be the one we always need.
So, let’s look at some of the formatting options. -g 1 is used to group by 1 byte. We can also use -c 8 to have 8 columns per line:
$ head -c 8 ~/Pictures/Image1.png | xxd -g 1 -c 8 00000000: 89 50 4e 47 0d 0a 1a 0a .PNG....
Finally, with -ps, we get plain hex values:
$ head -c 8 ~/Pictures/Image1.png | xxd -ps 89504e470d0a1a0a
And -i is used to printing in C, including file style. It is very helpful to initialize variables in C with binary data:
$ head -c 8 ~/Pictures/Image1.png | xxd -i 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a
5. Using the od Command
Next, we’ll look at the od command, typically used for converting between different formats. By default, it dumps the results in octal format. However, there are options to print the result in hexadecimal format.
Let’s take a look at that:
$ head -c 8 ~/Pictures/Image1.png | od -x 0000000 5089 474e 0a0d 0a1a 0000010
Here, after reading the file, we’ve used the od command with the -x option. As a result, it prints the data in hexadecimal format.
By default, this option will print 2 bytes in width. But, if we want to print one byte at a time, we can use the -t option.
Let’s check that:
$ head -c 8 ~/Pictures/Image1.png | od -t x1 0000000 89 50 4e 47 0d 0a 1a 0a 0000010
-t x1 formats the output in hexadecimal form with 1 byte at a time.
In this tutorial, we’ve seen different ways of converting binary data into hexadecimal format. With these commands, we can confidently deal with binary data.