hexdump and xxd: Inspecting Binary Data in Hex

hexdump and xxd: Inspecting Binary Data in Hex

What can you do with hexdump, xxd, and od?

Conclusion: All three display a file's bytes in hexadecimal. In practice, reach for hexdump -C or xxd first, use xxd -r when you need to edit, and keep od as the portable fallback.

  • Inspect a file's contents byte by byte in hex
  • Reveal invisible control characters, line endings (CRLF), and BOM bytes
  • Use xxd -r to edit a hex dump and turn it back into binary

The three tools in one line each

  • hexdump -C … the classic hex + ASCII view (most common on Linux)
  • xxd … readable, and with -r it reverses, with -i it emits a C array
  • od … the POSIX standard, oldest, your fallback when portability matters

Assumptions (target environment)

  • OS: Ubuntu / a typical Linux
  • hexdump and od ship with coreutils / bsdmainutils
  • xxd is part of the vim-common package (installed alongside vim on Ubuntu)

Why inspect binary data in hexadecimal?

Conclusion: To see the "invisible bytes" a text editor hides. Line-ending differences, a leading BOM, stray trailing whitespace, and broken encodings only become visible in a hex dump.

"The script won't run," "the diff won't match," "file detection is wrong" — these problems often hide a byte that never shows on screen.

  • A Windows line ending \r\n (CRLF) slipped in
  • A UTF-8 file carries a BOM (EF BB BF) at the start
  • A full-width space or control character crept in

These are hard to tell apart in a text editor, but a hex dump shows every byte exactly.

hexdump basics — always start with -C

Conclusion: The default hexdump output byte-swaps 16-bit words and is hard to read. In practice, always add -C (canonical) to line up hex on the left and ASCII on the right.

Create a sample file.

$ printf 'Hello, World!\n' > demo.txt

With -C, the offset, hex bytes, and ASCII sit on one line.

$ hexdump -C demo.txt
00000000  48 65 6c 6c 6f 2c 20 57  6f 72 6c 64 21 0a        |Hello, World!.|
0000000e

The leading 00000000 is the offset from the start of the file (in hex), the middle is each byte's hex value, and the |...| on the right is the ASCII view (non-printing bytes show as .).

Without -C it is hard to read

$ hexdump demo.txt
0000000 6548 6c6c 2c6f 5720 726f 646c 0a21
000000e

On a little-endian system this treats two bytes as one word and swaps them, so 48 65 appears as 6548. It is a common source of confusion — use -C when a human is reading.

Common options:

  • -n <length>: show only the first N bytes
  • -s <offset>: skip N bytes from the start
  • -v: show every line instead of collapsing repeats into *
$ hexdump -C -n 16 -s 0 demo.txt

xxd basics and its handy tricks

Conclusion: Plain xxd already prints a readable dump. Its real value is -r (hex back to binary), -p (plain hex), and -i (C array output) — the reverse direction hexdump cannot do.

Plain xxd groups hex two bytes at a time with an ASCII view on the right.

$ xxd demo.txt
00000000: 4865 6c6c 6f2c 2057 6f72 6c64 210a            Hello, World!.

Extract plain hex (-p)

-p (plain) prints a continuous hex string with no separators — easy to handle in scripts.

$ xxd -p demo.txt
48656c6c6f2c20576f726c64210a

Turn hex back into binary (-r)

The reverse flag -r is xxd's biggest strength. Edit a dump, then turn it back into the original binary.

$ xxd demo.txt | xxd -r
Hello, World!

To reverse from plain hex, add -p as well.

$ echo '48656c6c6f0a' | xxd -r -p
Hello

Emit a C array (-i)

-i (include) prints the file as a C byte array — handy for embedding firmware or test data.

$ xxd -i demo.txt
unsigned char demo_txt[] = {
  0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64,
  0x21, 0x0a
};
unsigned int demo_txt_len = 14;

Common options:

  • -l <length>: show only the first N bytes
  • -s <offset>: set the start position
  • -c <cols>: bytes per line (default 16)
  • -g <bytes>: bytes per group (default 2)

When should you use od?

Conclusion: od (octal dump) is the most portable — it is the POSIX standard. It works on minimal or embedded Linux where hexdump or xxd may be missing. od -A x -t x1z gives output equivalent to hexdump -C.

As the name suggests, od was originally an octal dump, but -t sets the display format and -A sets the offset radix.

$ od -A x -t x1z demo.txt
000000 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 0a  >Hello, World!.<
00000e
  • -A x: show offsets in hex (d for decimal, o for octal)
  • -t x1: display one byte at a time in hex
  • z: append an ASCII view at the end of each line

Other common formats:

  • od -c: show characters and escapes (\n, \t, and so on)
  • od -An -t x1: drop the offset and show hex bytes only

Because od's output is specified by POSIX, it is worth choosing od -A n -t x1 when portability of a script matters.

How do you choose between the three?

Conclusion: For everyday inspection use hexdump -C or xxd; to edit binary use xxd -r; for portable scripts use od. When in doubt, hexdump -C is enough.

Goal Recommended tool
Just see the contents hexdump -C
Readability, grouped view xxd
Edit hex and turn back to binary xxd -r
Embed as a C array xxd -i
Portability / minimal environment od -A x -t x1z

Where this matters in practice

Conclusion: Stray line endings, a BOM, and direct binary edits are the classic real-world cases. None can be judged reliably without a hex dump.

Find stray CRLF line endings

When \r\n (CRLF) sneaks in, you see 0d 0a — a 0d appears. A Unix newline \n is just 0a.

$ printf 'line1\r\nline2\n' | xxd
00000000: 6c69 6e65 310d 0a6c 696e 6532 0a          line1..line2.

The 0d in 310d 0a6c is the proof of CRLF. You can pinpoint a byte that the ASCII column only shows as ..

Check for a UTF-8 BOM

If EF BB BF sits at the start of a file, it is a UTF-8 BOM.

$ hexdump -C bom.txt
00000000  ef bb bf 68 69 0a                                 |...hi.|
00000006

The first three bytes ef bb bf are the BOM. When this prefixes a shell script, #!/bin/bash is not parsed correctly and the script fails to run.

Edit binary directly (round trip)

Dump with xxd, edit the hex in an editor, then restore with xxd -r — this lets you edit a single byte at a time.

$ xxd demo.txt > demo.hex
# edit demo.hex (for example, change 48 to 4a)
$ xxd -r demo.hex > demo_edited.txt

When restoring with xxd -r, keep the offset column and byte column consistent. Changing the byte count shifts the offsets and can produce unexpected results. Stick to minimal edits such as single-byte replacements.

Troubleshooting

Conclusion: xxd: command not found means vim-common is not installed. If the output is hard to read, check whether you forgot -C on hexdump.

xxd: command not found

xxd ships in the vim-common (or xxd) package. On minimal systems it may not be installed.

$ sudo apt install xxd

Where xxd is unavailable, fall back to od -A x -t x1z or hexdump -C.

hexdump output looks wrong

Without -C, the default shows byte-swapped 16-bit words. If the ASCII does not line up and it is hard to read, suspect a missing -C.

Repeated lines collapse into * on large files

hexdump and od collapse identical lines into *. To see every line, add -v.

$ hexdump -C -v largefile.bin | head

Next Reading