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 -Corxxdfirst, usexxd -rwhen you need to edit, and keepodas 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 -rto 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-rit reverses, with-iit emits a C arrayod… the POSIX standard, oldest, your fallback when portability matters
Assumptions (target environment)
- OS: Ubuntu / a typical Linux
hexdumpandodship with coreutils / bsdmainutilsxxdis part of thevim-commonpackage (installed alongsidevimon 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
hexdumpoutput 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
xxdalready 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 wherehexdumporxxdmay be missing.od -A x -t x1zgives output equivalent tohexdump -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 (dfor decimal,ofor octal)-t x1: display one byte at a time in hexz: 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 -Corxxd; to edit binary usexxd -r; for portable scripts useod. When in doubt,hexdump -Cis 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 foundmeansvim-commonis not installed. If the output is hard to read, check whether you forgot-Conhexdump.
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