Inspect Binary Files Safely with hexdump and hd

A file that will not open, a corrupted download, an unfamiliar format: hexdump shows you the raw bytes without touching the original. This guide covers inspecting a binary file, choosing a useful display, bounding a large read, and spotting when hexdump has abbreviated repeated data. Allow about ten minutes. The commands are normally unprivileged; use elevated access only if the file permissions genuinely require it, and prefer copying the file to a readable working directory when that is safe.

1. Confirm the command and version

This guide follows the installed Ubuntu manual page for bsdextrautils, which provides util-linux hexdump 2.39.3 on this machine. The command may also come from another util-linux release or a different package, so check the executable before relying on any option in a script:

$ command -v hexdump
/usr/bin/hexdump
$ hexdump --version | head -1
hexdump from util-linux 2.39.3
$ command -v hd
/usr/bin/hd

If command -v names a different executable, read that installation's manual page instead. hd is an alias-style invocation of the same utility: running it as hd implies the canonical hex plus ASCII display.

Checkpoint: you know which executable will run, and its version matches the behaviour you are about to test.

2. Start with a canonical hex and ASCII view

Use -C when you want offsets, byte values and a readable character column. The offset is hexadecimal, each row holds up to sixteen bytes, and non-printing bytes show as full stops in the ASCII column.

$ hexdump -C /path/to/input.bin
00000000  48 65 6c 6c 6f 0a 00 01  ff 0a 48 65 6c 6c 6f 0a  |Hello.....Hello.|
00000010

That final offset marks the end of this example's 16-byte input; the exact rows depend on your file. This is a read-only operation: hexdump reads the named file and writes the display to standard output.

The shorter form is handy at the terminal:

$ hd /path/to/input.bin

Do not confuse the display with a text conversion. The original bytes are unchanged, and copying the visible hexadecimal characters back into a file would create a different file entirely.

3. Limit the amount and starting position

Inspect a small region of a large file with -s for the starting byte offset and -n for the maximum number of bytes. Both accept suffixes such as K or MiB; K means 1024, while KB means 1000.

$ hexdump -C -s 1KiB -n 64 /path/to/disk-image.bin
00000400  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000410  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000430  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

This reads at most 64 bytes starting at offset 1024. The offset in the output is the file offset, not zero-based within the selected slice. Use -n when the input is a device or a pipe and you need a bounded read.

Warning: never point exploratory commands at a live device unless you understand what it represents. Reading is less risky than writing, but it can still expose sensitive data.

Checkpoint: before examining a large or sensitive input, state the intended offset and length in the command itself.

4. Choose another representation

The short options select fixed layouts: -x for two-byte hexadecimal units, -d for two-byte unsigned decimal, -o for two-byte octal, -b for one-byte octal, or -c for one-byte characters.

$ printf 'ABCD' | hexdump -e '4/1 "%02x " "\n"'
41 42 43 44

That -e example uses a custom format: the leading number repeats the format four times, /1 consumes one byte per repetition, and %02x prints each byte as two lower-case hex digits. Keep the format string quoted so the shell does not chew on its punctuation.

For a format you will reuse, -f FORMAT_FILE reads newline-separated format strings, ignoring blank lines and lines whose first non-blank character is #. Treat a format file as executable input: inspect it before use, especially one that came from someone else.

5. Do not mistake an asterisk for missing data

By default, consecutive rows that would be identical apart from their offsets can be collapsed into a single line containing an asterisk. That saves space, it does not mean the bytes were skipped.

$ hexdump -C /path/to/mostly-empty.bin
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000040

Use -v when every row must be printed, for example when comparing output line by line or capturing an audit record:

$ hexdump -v -C /path/to/mostly-empty.bin

Check the exit status when scripting: zero means the command completed successfully, non-zero means an error occurred, such as an unreadable or missing input. The command does not repair a malformed file and does not identify the file format for you.

6. Keep output and permissions under control

Output goes to standard output, so only redirect it once you have chosen the destination deliberately: shell redirection with > truncates an existing file before hexdump even starts. For a report, write to a new name or a temporary file, inspect it, then replace the target:

$ hexdump -C /path/to/input.bin > /path/to/input.hex.new
$ test -s /path/to/input.hex.new && head -3 /path/to/input.hex.new
$ mv /path/to/input.hex.new /path/to/input.hex

Warning: that mv changes the filesystem and can replace an existing destination. Stop before that line if the destination matters, and choose a backup or a different name. If the hexdump command fails, remove the incomplete .new file rather than treat it as a valid report. There is no need for sudo when reading files you already own.

Done means