In shell, how can I read the bytes of a binary file I have, and print the output as hexadecimal numbers?
8 Answers
Use hexdump(1)
$ hexdump -x /usr/bin/hexdump
0000000 feca beba 0000 0300 0001 0700 0080 0300
0000010 0000 0010 0000 5080 0000 0c00 0000 0700
0000020 0000 0300 0000 00a0 0000 b06f 0000 0c00
0000030 0000 1200 0000 0a00 0100 0010 0000 107c
0000040 0000 0c00 0000 0000 0000 0000 0000 0000
0000050 0000 0000 0000 0000 0000 0000 0000 0000
...
-
10Also check out
od
. There is also a vi-style hex editor calledhexer
. Commented Apr 7, 2011 at 14:47 -
14I like the output of "hexdump -C file" better. xxd is also a nice tool.– KambusCommented Apr 7, 2011 at 17:09
-
1show in bash hexa format
hexdump -e '"\\\x" /1 "%02x"' filename
Commented Nov 20, 2014 at 16:10 -
4For information, the first column is the hexadecimal offset of the bytes, the rest of the line is 8 sets of two-byte displays, i.e. 16 bytes, which is why the second line starts with an offset of
10
, which is 16 in hexadecimal. The two-byte representation depends on the endianness of the system. Typeman hexdump
for the full details.– emonigmaCommented Dec 7, 2018 at 13:23 -
my above trick is bad, hexdump will output '*\n' for any repeating bytes. I am using this instead:
... |od -A n -t x1 |tr -d ' \n'
Commented Aug 20, 2023 at 23:50
Another option is od:
od -t x1 FILE
sample output:
$ printf '0123456789abcdef0123456789abcdef\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' | od -t x1
0000000 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66
*
0000040 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0000060
or
od -x FILE
sample output:
0000000 3130 3332 3534 3736 3938 6261 6463 6665
*
0000040 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e
0000060
od
has many options for finetuning.
-
12
-
For the line
od -t test
I gotod: invalid character 't' in type string 'test'
– StudentCommented Apr 11, 2011 at 13:52 -
1
-
@Tom: Maybe a different Unix/Linux flavor? My od is:
od --version od (GNU coreutils) 7.4
Commented Apr 11, 2011 at 15:01 -
If it can help somebody else, I wanted to have the last 4 bytes in hex of a binary file. Here is what I did that works. od -A n -t x1 -w1 -v myFile.bin | tail -n 4 | sed 's/ //g' | paste -sd ''– mgouinCommented Feb 17, 2022 at 18:53
While we're on od
and hexdump
, two more similar tools:
- hd (from bsdmainutils)
- xxd (part of Vim)
Sample output:
$ hd /usr/bin/od | head
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 03 00 01 00 00 00 20 8e 04 08 34 00 00 00 |........ ...4...|
00000020 a4 a2 00 00 00 00 00 00 34 00 20 00 08 00 28 00 |........4. ...(.|
00000030 1b 00 1a 00 06 00 00 00 34 00 00 00 34 80 04 08 |........4...4...|
00000040 34 80 04 08 00 01 00 00 00 01 00 00 05 00 00 00 |4...............|
00000050 04 00 00 00 03 00 00 00 34 01 00 00 34 81 04 08 |........4...4...|
00000060 34 81 04 08 13 00 00 00 13 00 00 00 04 00 00 00 |4...............|
00000070 01 00 00 00 01 00 00 00 00 00 00 00 00 80 04 08 |................|
00000080 00 80 04 08 c4 9d 00 00 c4 9d 00 00 05 00 00 00 |................|
00000090 00 10 00 00 01 00 00 00 00 a0 00 00 00 20 05 08 |............. ..|
$ xxd /usr/bin/od | head
0000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
0000010: 0200 0300 0100 0000 208e 0408 3400 0000 ........ ...4...
0000020: a4a2 0000 0000 0000 3400 2000 0800 2800 ........4. ...(.
0000030: 1b00 1a00 0600 0000 3400 0000 3480 0408 ........4...4...
0000040: 3480 0408 0001 0000 0001 0000 0500 0000 4...............
0000050: 0400 0000 0300 0000 3401 0000 3481 0408 ........4...4...
0000060: 3481 0408 1300 0000 1300 0000 0400 0000 4...............
0000070: 0100 0000 0100 0000 0000 0000 0080 0408 ................
0000080: 0080 0408 c49d 0000 c49d 0000 0500 0000 ................
0000090: 0010 0000 0100 0000 00a0 0000 0020 0508 ............. ..
Or, if you want to read the bytes one at a time and print them in your own format, try something like:
while read -n 1 byte; do
ord=$(printf "%b" "${byte:-\000}" |
od -t x1 |
{ read offset hex; echo $hex; })
echo "$ord"
done </usr/bin/od
Sample output:
7f
45
4c
46
01
01
01
00
00
00
-
4unlike the other, xxd is also able to revert the modification. With that, it is possible to alter a binary file with shell.– OffirmoCommented Jun 11, 2012 at 16:31
-
2Your
while
loop doesn't work for backslash and newline characters (and in bash (as opposed to ksh93) for blank characters), nor will it work properly in utf8 locales for bytes with the 8th bit set. Also, you don't need "od" there, you can useprintf '%02x\n' "'$byte"
Commented Oct 15, 2012 at 20:13 -
Note:
offset
is merely a sort of "dummy variable" here; it has no practical use. It is just used as a placeholder to get tohex
. This is what sometimes affects readability in a negative way withread
: variables coming out of the blue. Commented Dec 2, 2014 at 0:01 -
Perhaps. But in this case, the scope of
$offset
is limited by the subshell, so I don't see it as a problem.– MikelCommented Dec 2, 2014 at 3:44 -
My two cents:
tail -f streamfile | hexdump -C
I like this because you are tailing a currently buffering file while being able to see the hexdump live. Don't forget that EVERYTHING in Unix is a file and we can easily chain commands like tail
and hexdump
to solve a wide variety of problems.
-
tested with
for((i=0;i<100;i++));do echo $i >>tst2.bin;sleep 1;done&
it works well for monitoring thx :) Commented Nov 20, 2014 at 15:56
mc
The midnight commander is another option. I don't know whether it is available for all unix flavors. You might need to download it first.
F3 F4 to view in internal editor/ in hex mode.
I use od with c and x1, when I need to search for text inside the binary file:
$ echo "Some text..." | od -t c -t x1
0000000 S o m e t e x t . . . \n
53 6f 6d 65 20 74 65 78 74 2e 2e 2e 0a
0000015
If the data you're viewing is mostly text with occasional binary, you might find the -v
option to cat(1)
convenient:
$ printf 'here is\x00\x01some text\x15\x16with the odd bit\x80\x81of binary mixed in' | cat -v
here is^@^Asome text^U^Vwith the odd bitM-^@M-^Aof binary mixed in
Non-printing bytes ≤ 0x7f
are displayed with control-character notation. Bytes ≥ 0x80
are prefixed by M-
.
This isn't reversible since M-
itself doesn't appear to be escaped. Nonetheless, it can be easier to read than the full canonical hex dump format given by hd(1)
and other tools.
Get raw hex byte string without any formatting
This form can also be useful when you want to convert data rather than view it manually:
od -An -v -tx1 | tr -d ' \n'
Example:
printf '0123456789abcdef0123456789abcdef\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' | od -An -v -tx1 | tr -d ' \n'
Output:
3031323334353637383961626364656630313233343536373839616263646566000102030405060708090a0b0c0d0e0f
So no spaces or newlines, just the hex.
Tested on Ubuntu 23.04.
Related: https://stackoverflow.com/questions/2003803/show-hexadecimal-numbers-of-a-file