Right, so cat and less are great until they aren’t. You try to cat a binary executable, and your terminal immediately starts screaming at you with a combination of beeps, garbled symbols, and the occasional legible string like “/lib64/ld-linux-x86-64.so.2”. It’s a mess. You’ve just angered the TTY gods. This is where our good friends xxd and od come in—they’re your polite, orderly translators for the raw, unfiltered truth of what’s actually in a file, byte by byte.

These tools don’t interpret the data as text or code; they just show it to you, faithfully, in its most fundamental form: numbers. xxd shows it in hexadecimal (hex), which is the lingua franca of low-level work. od (octal dump) is its older, more POSIX-standardized cousin that can show you data in a bewildering array of formats, from the archaic (octal) to the useful (hex, ASCII).

The Go-To: xxd (The Hex Dump Powerhouse)

xxd is, frankly, what most people want most of the time. It’s clean, it’s intuitive, and it’s probably already on your system. Its default output is a thing of beauty: three columns of goodness.

Run it on a simple text file to see the canonical view:

echo "Hello, Planet!" > hello.txt
xxd hello.txt

You’ll get something like this:

00000000: 4865 6c6c 6f2c 2050 6c61 6e65 7421 0a  Hello, Planet!.

Let’s break down this hieroglyphic. You’ve got three parts:

  1. The Offset (00000000): This is the memory address, in hex, of where this line of data begins in the file. It’s your cursor, telling you “this chunk of data starts at byte zero.”
  2. The Hexadecimal Bytes (4865 6c6c…): This is the raw data. Each two-character pair represents one single byte. 48 is the hex value for the ASCII character ‘H’. 65 is ’e’. 6c is ’l’. You get the idea. The bytes are grouped, usually in sets of two, just to make it easier for our pattern-matching brains to read.
  3. The ASCII Representation (Hello, Planet!.): This is the right-hand column. xxd takes each byte and asks, “If I squint and pretend this is text, what character would this byte represent?” If the byte doesn’t correspond to a printable ASCII character, it just prints a . (a dot)—a silent admission that some things are not meant for human eyes. The . at the end (0a) is the linefeed character, which is a non-printable control character.

The real power comes with its flags. Want to see only the first 32 bytes? Use -l (for limit).

xxd -l 32 /bin/ls

This is your best friend for peeking at the header of a file to see its magic number, the few bytes at the beginning that identify the file type. Is it a PNG? (89 50 4E 47), a PDF? (25 50 44 46), a ZIP file? (50 4B 03 04). xxd will show you.

But here’s the killer feature: xxd is reversible. You can create a hex dump, edit the ASCII or hex values in a text editor (carefully!), and then convert it back to binary. This is how you patch binaries without a full-blown hex editor.

xxd my_file.bin > my_file.hex
# ... edit my_file.hex carefully ...
xxd -r my_file.hex > my_file_patched.bin

The Original: od (Octal Dump, But So Much More)

Now, od. It’s the old guard, compliant with everything, and its default behavior is a historical artifact: it dumps in octal. Nobody wants this. Let’s just get that out of the way.

od hello.txt
0000000 062150 066545 026554 020544 064554 066551 024541 000012
0000020

What in the actual hell is that? This is why you always, always specify the output format with -t. To get the same useful output as xxd, you’d use:

od -t x1 -t c hello.txt

The -t flag specifies the output type. You can use multiple -t flags, and od will dutifully print both. Here, x1 means hex, one byte at a time (crucial for clean output), and c means printable character or backslash escape.

So why use od? Two reasons. First, it’s everywhere, even on minimalist systems where xxd might not be installed. Second, its -t flag is incredibly flexible. Want to see the same data interpreted as 4-byte decimal integers? For science?

od -t u4 hello.txt

It’s mostly useless for a text file, but it demonstrates the power. You can see data as signed/unsigned decimals, floats, hex with different byte groupings, and more. It’s the tool for when you need to ask very specific, very weird questions about a binary data structure.

Best Practices and Pitfalls

  1. Pipe it to less: The output can be long. Always use xxd my_binary_file | less or od -t x1 my_binary_file | less. You can then scroll and search.
  2. The Offset is Your Map: The offset is your absolute best friend for navigating. If you’re looking for a specific string you see in the ASCII column, note its offset. You can then use xxd -s 0x4d to seek to that exact location and see what surrounds it.
  3. Beware of Endianness: This is an advanced but critical point. When od or xxd groups bytes (e.g., xxd’ default grouping of 2 bytes, or od -t x4), it’s showing them in the machine’s native byte order (endianness). The bytes 01 02 in the file can be displayed as the 16-bit hex value 0x0102 (big-endian) or 0x0201 (little-endian). For most basic inspection, this doesn’t matter, but the moment you’re dealing with multi-byte numbers in a binary file format, it becomes everything. xxd -g 1 forces a one-byte grouping, showing you the raw byte sequence without any interpretation, which is often the safest view.
  4. od’s -A Flag: Use od -A x -t x1 -t c to make the address offset print in hex (x) instead of octal, which is far more sane. It’s the little things.

So, xxd is your daily driver—fast, clean, and reversible. od is your niche specialist—standards-compliant and endlessly configurable for when you have a strange question. Together, they’re your unfiltered lens into the bits and bytes that make up your digital world.