# od

_Peios / Using Peios / Peiosutils / Viewing and joining text_

> Dump the raw bytes of a file in octal, hexadecimal, decimal, floating-point, or character form — a low-level view of exactly what a file contains.

`od` — short for "octal dump" — prints the raw bytes of a file. Where [`cat`](/peios/using-peios/peiosutils/viewing-and-joining-text/cat.md) shows you a file as text, `od` shows you the actual bytes underneath: each one rendered as a number, a character, or a floating-point value, in whatever base you ask for. It is the tool for looking at binary files, checking exactly which bytes a text file contains, or finding a stray control character that isn't visible on screen.

```
od [options] [file...]
```

```
$ od hello.txt
0000000 062510 066154 020157 067527 066162 020144 000012
0000015
```

With no file — or with the name `-` — `od` reads standard input, so it can sit at the end of a pipeline. Given several files, it reads them one after another as a single continuous stream, and the byte offsets run straight through from one file into the next.

## How the output is laid out

Every line of output has two parts:

- An **offset** on the left: the position, counted in bytes from the start of the input, of the first byte on that line. By default it is printed in octal (see [`-A`](#the-offset-column) to change the base).
- One or more **format columns** on the right: the bytes of that line rendered in the format(s) you chose.

With no format option, `od` prints the input as **octal, two bytes at a time** — the traditional default. The very last line of output is a lone offset marking the total length of the input.

If you ask for more than one format at once, each format is printed on its own line, stacked under a single shared offset. Only the first line of the group carries the offset; the rest are indented to line up beneath it.

## Choosing what the bytes look like

There are two ways to say how bytes should be rendered: a set of single-letter **named shortcuts** for the common cases, and the general **`-t` / `--format`** option for full control. You can give several at once, and they are applied in the order they appear on the command line.

### Named format shortcuts

Each of these selects one output format. Combine them freely (`od -cx` prints characters and hex together).

| Option | Renders each unit as |
|---|---|
| `-a` | Named characters, ignoring the high-order bit (control characters shown by name, e.g. `nul`, `sp`, `del`). |
| `-b` | Octal, one byte at a time. |
| `-c` | Printable ASCII / UTF-8 characters, with backslash escapes (`\n`, `\t`, …) for the rest. |
| `-d` | Unsigned decimal, 2-byte units. |
| `-D` | Unsigned decimal, 4-byte units. |
| `-o` | Octal, 2-byte units. |
| `-O` | Octal, 4-byte units. |
| `-s` | Signed decimal, 2-byte units. |
| `-i` | Signed decimal, 4-byte units. |
| `-l` | Signed decimal, 8-byte units. |
| `-I`, `-L` | Signed decimal, 8-byte units. |
| `-x`, `-h` | Hexadecimal, 2-byte units. |
| `-X`, `-H` | Hexadecimal, 4-byte units. |
| `-f` | Floating point, single precision (32-bit). |
| `-e`, `-F` | Floating point, double precision (64-bit). |

### Type specifications (`-t`, `--format`)

`-t` takes a **type specification** and gives you every combination the named shortcuts cover and more. Repeat `-t` (or list several specs in one argument) to print multiple formats.

A type specification is a **type letter**, an optional **size**, and an optional **`z`** suffix:

| Type letter | Meaning |
|---|---|
| `a` | Printable 7-bit ASCII, named (like `-a`). |
| `c` | UTF-8 characters, with octal escapes for undefined bytes (like `-c`). |
| `d` | Signed decimal. |
| `u` | Unsigned decimal. |
| `o` | Octal. |
| `x` | Hexadecimal. |
| `f` | Floating point. |

For the numeric types (`d`, `u`, `o`, `x`, `f`) a **size** says how many bytes make up one unit. It can be a number, or a letter:

| Size | Applies to | Bytes per unit |
|---|---|---|
| `1` / `C` | integer types | 1 |
| `2` / `S` | integer types | 2 |
| `4` / `I` | integer types | 4 |
| `8` / `L` | integer types | 8 |
| `4` / `F` | floating point | 4 (single precision) |
| `8` / `D` | floating point | 8 (double precision) |
| `16` / `L` | floating point | 16 (extended / long double) |
| `2` / `H` | floating point | 2 (IEEE half precision) |
| `2` / `B` | floating point | 2 (bfloat16) |

If you leave the size off, integer types default to **4 bytes** and floating point defaults to **8 bytes**. For the character types `a` and `c`, a size is not allowed.

Add a **`z`** at the end of a spec to append an ASCII dump — the bytes of that line shown as text, `.` for anything non-printable — to the right of the numbers. For example, `od -t x1z` gives the familiar hex-plus-text layout:

```
$ od -A x -t x1z file.bin
000000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a           >Hello, world!.<
```

Examples: `od -t d2` is signed decimal in 2-byte units; `od -t x1` is hex byte-by-byte; `od -t fD` is double-precision floats; `od -t c` is characters. `od -t x1 -t c` prints hex and characters as two stacked lines.

### Byte order (`--endian`)

For multi-byte numeric formats, `--endian` sets the byte order used to assemble each unit. Without it, `od` uses the machine's native byte order. Use `--endian=big` or `--endian=little` to force one regardless of the host.

## The offset column

| Option | Effect |
|---|---|
| `-A RADIX`, `--address-radix=RADIX` | Print offsets in the given base. `RADIX` is one of `o` (octal, the default), `d` (decimal), `x` (hexadecimal), or `n` (none — omit the offset column entirely). |

Only the first character of the value is examined, so `od -A n` and `od -Anone` mean the same thing.

## Which bytes to read

By default `od` dumps the whole input. Two options narrow that to a window:

| Option | Effect |
|---|---|
| `-j BYTES`, `--skip-bytes=BYTES` | Skip `BYTES` bytes of input before starting to dump. When several files are given, the skip runs across the concatenated stream. |
| `-N BYTES`, `--read-bytes=BYTES` | Dump at most `BYTES` bytes, then stop. |

In both, `BYTES` is decimal by default, octal if it starts with `0`, or hexadecimal if it starts with `0x`. A suffix scales it: `b` = ×512, `KB`/`K` = ×1000 / ×1024, `MB`/`M` = ×1000² / ×1024², `GB`/`G` = ×1000³ / ×1024³.

## Collapsing repeated lines

When several output lines in a row would be identical, `od` prints the first one, then a single line containing just `*` to stand for the run, and resumes at the next line that differs. This keeps a dump of a large block of identical bytes (a file full of zeros, say) short.

| Option | Effect |
|---|---|
| `-v`, `--output-duplicates` | Turn the collapsing off — print every line, including repeats, with no `*` markers. |

## Output width

| Option | Effect |
|---|---|
| `-w[BYTES]`, `--width[=BYTES]` | Print `BYTES` input bytes per output line. The default is 16; giving `-w` with no value uses 32. |

The width must be a whole multiple of the size of the largest format unit in play; if it isn't, `od` warns and rounds it to a usable value.

## Finding printable strings

| Option | Effect |
|---|---|
| `-S[BYTES]`, `--strings[=BYTES]` | Instead of dumping bytes, scan the input and print only runs of at least `BYTES` printable characters, one per line, each preceded by its offset. `BYTES` defaults to 3 when omitted. |

This turns `od` into a quick way to pull the human-readable text out of a binary file. The offset in front of each string honours `-A` (and is dropped entirely under `-A n`). `-j` and `-N` still apply, so you can restrict the scan to a window.

## The traditional offset form

`od` also accepts the historical calling convention, where an **offset** (and, in `--traditional` mode, a **label**) is given as a bare operand rather than an option:

```
od [named-format-options] [file] [[+]offset[.][b]]
od --traditional [options] [file] [[+]offset[.][b] [[+]label[.][b]]]
```

The **offset** says where in the input to begin, exactly like `-j`. It is read as **octal by default**, hexadecimal if prefixed with `0x`, or decimal if it carries a trailing `.`; a trailing `b` multiplies it by 512. The optional leading `+` is allowed everywhere and is required when there is no filename (so `od +20` reads standard input starting at octal offset 20).

The **label** (only in `--traditional` mode) is a second such number: the dump still begins at `offset`, but the offset column is *displayed* as if it started at `label` — useful for making a partial dump's offsets match the original file.

`od` only reads an operand as an offset in the plain form when none of `-A`, `-j`, `-N`, `-t`, `-v`, or `-w` are present. So if a real filename happens to look like a number, add a harmless option such as `-j0` to force it to be treated as a filename.

## A note on reading files

`od` has no access rules of its own — it simply opens a file and reads its bytes. That read is subject to the same check as every read on Peios: whether you may open the file for reading is decided by the file's **security descriptor** (see [Security descriptors](/peios/security-fundamentals/security-descriptors/overview.md)). `od` never reveals bytes you could not already read another way; it only presents the bytes you can read in a different form.

## Exit status

| Code | Meaning |
|---|---|
| `0` | The input was dumped successfully. |
| `1` | A file could not be read, or an option, format, or offset was invalid. |

Related content:

- [cat](/peios/using-peios/peiosutils/viewing-and-joining-text/cat.md)
- [Viewing and joining text](/peios/using-peios/peiosutils/viewing-and-joining-text/overview.md)
- [Security descriptors](/peios/security-fundamentals/security-descriptors/overview.md)
