Format roff source for readable terminal output with nroff
You will turn a small roff document into readable terminal output, choose the character encoding deliberately, and check the command without running it when troubleshooting. Allow about fifteen minutes. The examples use GNU nroff 1.23.0 from groff-base 1.23.0-3build2, installed on this machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide assumes a shell and a document written for the groff roff language. It does not need elevated privileges. It reads the source and writes formatted text to standard output unless you redirect it yourself.
1. Check the installed nroff
Confirm which executable your shell will run and record its version:
$ command -v nroff
/usr/bin/nroff
$ nroff --version
GNU nroff (groff) version 1.23.0
The version matters because nroff is a front end to groff, and the available behaviour belongs to the installed groff release. Ask for the usage summary if you need to confirm option spelling:
$ nroff --help
usage: /usr/bin/nroff [-bcCEhikpRStUVz] [-d ctext] [-d string=text] [-K fallback-encoding] [-m macro-package] [-M macro-directory] [-n page-number] [-o page-list] [-P postprocessor-argument] [-r cnumeric-expression] [-r register=numeric-expression] [-T output-device] [-w warning-category] [-W warning-category] [file ...]
Checkpoint: if command -v finds nothing, install the distribution package that supplies nroff through your normal package-management process. Do not add a random copy to PATH while diagnosing a formatting difference.
2. Render a roff document from standard input
Use the -man macro package for man-page style input. This example supplies a title, a name section and a description, then sends the result to your terminal:
$ printf '.TH DEMO 1\n.SH NAME\ndemo \\- example\n.SH DESCRIPTION\nA short test.\n' | nroff -man -Tutf8
DEMO(1) General Commands Manual DEMO(1)
NAME
demo - example
DESCRIPTION
A short test.
The terminal may receive control sequences for bold or underlined text, so the visible result can differ from the plain text shown above. nroff formats for a typewriter-like device; it does not produce a PDF or a web page.
-man selects the installed man macro package. -Tutf8 selects UTF-8 terminal output. The input is supplied through standard input, so no temporary source file is needed for a quick test.
3. Render an existing file
Give the source file after the options. Replace the placeholder with a real path:
$ nroff -man -Tutf8 /path/to/example.1
To save text for a review, redirect standard output to a new destination:
$ nroff -man -Tutf8 /path/to/example.1 > /path/to/example.txt
$ test -s /path/to/example.txt && echo 'formatted output is non-empty'
formatted output is non-empty
Shell redirection with > truncates an existing destination before nroff starts. That is a state-changing action, even though nroff itself only reads the source. Use a new filename first if the old output matters:
$ nroff -man -Tutf8 /path/to/example.1 > /path/to/example.txt.new
$ mv /path/to/example.txt.new /path/to/example.txt
If formatting fails, remove the incomplete .new file and the previous output remains in place. Do not use sudo for ordinary rendering. If the destination directory is not writable, choose a directory you own rather than changing permissions without a reason.
4. Choose the output device when characters matter
GNU nroff accepts ascii, latin1, utf8 and cp1047 as -T devices. On this machine, UTF-8 is a sensible default for a UTF-8 terminal:
$ printf '.TH DEMO 1\n.SH NAME\ndemo \\- example\n' | nroff -man -Tutf8
Use ASCII when the receiving terminal or log consumer cannot handle the terminal character set:
$ printf '.TH DEMO 1\n.SH NAME\ndemo \\- example\n' | nroff -man -Tascii
If you omit -T, nroff can select a device from GROFF_TYPESETTER or the locale-related environment variables, including LC_ALL, LC_CTYPE and LANG. If no valid choice is found, it falls back to ASCII. An explicit -T overrides GROFF_TYPESETTER, which makes scripts easier to review.
5. Inspect the constructed command without executing it
When output differs between environments, -V prints the groff command that nroff would construct and does not execute it:
$ printf '.TH DEMO 1\n.SH NAME\ndemo \\- example\n' | nroff -man -Tutf8 -V
PATH=... groff -Tutf8 -mtty-char -man
The exact PATH value and spacing depend on the environment. The useful checks are that the selected device and macro package are present. Treat this as diagnostics, not as a replacement command to paste blindly: it can expose environment-dependent paths.
For a syntax or macro warning, add the warning options supported by groff, or use -w and -W with a warning category documented by groff(1). Keep the source unchanged until you know whether the issue is input, macro selection or terminal encoding.
6. Distinguish output suppression from successful formatting
The -z option suppresses formatted output while still running the formatter. It is useful for a quiet check of a source file:
$ printf '.TH DEMO 1\n.SH NAME\ndemo \\- example\n' | nroff -man -z > /tmp/nroff-check.out
$ printf 'status=%s, bytes=%s\n' "$?" "$(wc -c < /tmp/nroff-check.out)"
status=0, bytes=0
A zero status means the formatter completed successfully for this input; it does not mean a normal output file was produced. Remove this temporary file after checking if you do not need it. Do not confuse -z with a dry run of every external effect in a larger document: macro packages can invoke groff features beyond the visible text.
7. Diagnose the usual failures
An argument-parsing problem returns status 2. A successful -V, -v, --version or --help invocation returns status 0 without formatting the document. Otherwise, nroff returns groff's status:
$ nroff --definitely-not-an-option >/dev/null
$ printf 'status=%s\n' "$?"
status=2
If a file cannot be opened, check its path and readability without changing it:
$ ls -l /path/to/example.1
$ test -r /path/to/example.1 && echo readable
If output looks like raw roff requests, check that the document uses the macro package it expects, such as -man. If characters are damaged in a log or pager, make -Tutf8 or -Tascii explicit and check the consumer's encoding. Pagers such as less may need their own options to display terminal control sequences correctly; nroff does not configure the pager for you.
Done means
nroff --versionidentifies the installed GNU groff release.- A roff document renders through
-manto the intended terminal device. - Saved output was written to a new path before any replacement was made.
-Vwas used to inspect environment-sensitive command construction when needed.-zwas treated as output suppression, not proof that a normal output file exists.