217

How do I create an unmodified hex dump of a binary file in Linux using bash? The od and hexdump commands both insert spaces in the dump and this is not ideal.

Is there a way to simply write a long string with all the hex characters, minus spaces or newlines in the output?

David Raswik
  • 2,171
  • 2
  • 13
  • 3
  • See also: [How to print only the hex values from hexdump without line numbers or ASCII table?](https://stackoverflow.com/questions/15553493/how-to-print-only-the-hex-values-from-hexdump-without-line-numbers-or-ascii-tabl) – 0x90 Jul 26 '17 at 21:29

9 Answers9

282
xxd -p file

Or if you want it all on a single line:

xxd -p file | tr -d '\n'
Giacomo1968
  • 24,837
  • 11
  • 67
  • 96
mark4o
  • 55,879
  • 16
  • 84
  • 100
113

Format strings can make hexdump behave exactly as you want it to (no whitespace at all, byte by byte):

hexdump -ve '1/1 "%.2x"'

1/1 means "each format is applied once and takes one byte", and "%.2x" is the actual format string, like in printf. In this case: 2-character hexadecimal number, leading zeros if shorter.

John Gibb
  • 10,372
  • 2
  • 36
  • 47
Michał Trybus
  • 10,996
  • 3
  • 27
  • 41
  • 7
    You need a `-v` or it will drop repeated bytes and replace them with an asterisk. – Dennis Williamson Apr 10 '10 at 22:35
  • 2
    I wonder if hexdump itself is able to append the newline (only) to the end of output.. (obvious appendage of `; echo` makes it impossible to use as bash alias) – mykhal Aug 22 '15 at 17:57
  • 3
    My alias: `alias to_hex="hexdump -ve '1/1 \"%.2x\"' && echo"` – devstuff Feb 16 '18 at 22:19
  • The iteration count and byte count default to one, so 1/1 may be omitted, leaving the `hexdump -ve '"%.2x"'` – Alex Che Sep 27 '18 at 10:16
  • @mykhal, it's possible, if you know the number of bytes in output. Say if you use hexdump to output only 13 first bytes: `hexdump -n 13 -e '13/1 "%.2x" "\n"'` – Alex Che Sep 27 '18 at 10:58
  • You can reverse this output back into a binary with `xdd -p -r < dump > file` – dagelf Nov 03 '21 at 09:04
26

It seems to depend on the details of the version of od. On OSX, use this:

od -t x1 -An file |tr -d '\n '

(That's print as type hex bytes, with no address. And whitespace deleted afterwards, of course.)

Donal Fellows
  • 126,337
  • 18
  • 137
  • 204
10

Perl one-liner:

perl -e 'local $/; print unpack "H*", <>' file
Alan Haggai Alavi
  • 69,934
  • 19
  • 98
  • 125
3

The other answers are preferable, but for a pure Bash solution, I've modified the script in my answer here to be able to output a continuous stream of hex characters representing the contents of a file. (Its normal mode is to emulate hexdump -C.)

Community
  • 1
  • 1
Dennis Williamson
  • 324,833
  • 88
  • 366
  • 429
1

I think this is the most widely supported version (requiring only POSIX defined tr and od behavior):

cat "$file" | od -v -t x1 -A n | tr -d ' \n'

This uses od to print each byte as hex without address without skipping repeated bytes and tr to delete all spaces and linefeeds in the output. Note that not even the trailing linefeed is emitted here. (The cat is intentional to allow multicore processing where cat can wait for filesystem while od is still processing previously read part. Single core users may want replace that with < "$file" od ... to save starting one additional process.)

Mikko Rantalainen
  • 11,523
  • 10
  • 66
  • 98
1

This code produces a "pure" hex dump string and it runs faster than the all the other examples given. It has been tested on 1GB files filled with binary zeros, and all linefeeds. It is not data content dependent and reads 1MB records instead of lines.

perl -pe 'BEGIN{$/=\1e6} $_=unpack "H*"'

Dozens of timing tests show that for 1GB files, these other methods below are slower. All tests were run writing output to a file which was then verified by checksum. Three 1GB input files were tested: all bytes, all binary zeros, and all LFs.

hexdump -ve '1/1 "%.2x"'                    #  ~10x  slower
od -v -t x1 -An | tr -d "\n "               #  ~15x  slower
xxd -p | tr -d \\n                          #   ~3x  slower
perl -e 'local \$/; print unpack "H*", <>'  # ~1.5x  slower
- this also slurps the whole file into memory

To reverse the process:

perl -pe 'BEGIN{$/=\1e6} $_=pack "H*",$_'
Gyre
  • 11
  • 3
0

tldr;

$ od -t x1 -A n -v <empty.zip | tr -dc '[:xdigit:]' && echo 
504b0506000000000000000000000000000000000000
$

Explanation:

Use the od tool to print single hexadecimal bytes (-t x1) --- without address offsets (-A n) and without eliding repeated "groups" (-v) --- from empty.zip, which has been redirected to standard input. Pipe that to tr which deletes (-d) the complement (-c) of the hexadecimal character set ('[:xdigit:]'). You can optionally print a trailing newline (echo) as I've done here to separate the output from the next shell prompt.

References:

rubicks
  • 4,312
  • 1
  • 26
  • 36
0

You can use Python for this purpose:

python -c "print(open('file.bin','rb').read().hex())"

...where file.bin is your filename.

Explaination:

  1. Open file.bin in rb (read binary) mode.
  2. Read contents (returned as bytes object).
  3. Use bytes method .hex(), which returns hex dump without spaces or new lines.
  4. Print output.
Vlad Havriuk
  • 954
  • 13
  • 24