Home / Alt manpages / pod2man(1)

  • pod2man(1)
  • User command
  • linux

Build a Reliable Man Page from POD with pod2man

By the end of this guide, you will have converted a small POD document into a section 1 manual page, checked it with man, and made its metadata predictable. The same workflow also handles POD embedded in a Perl script.

Prerequisites: the perl package, a shell, and a text editor. This takes about 10 minutes for a small document. The examples were checked with Perl 5.38.2 on Ubuntu, where pod2man reports documentation generated for perl v5.38.2.

Checkpoint: know what pod2man produces

pod2man is a wrapper around Perl's Pod::Man module. It reads POD and writes formatted *roff source. That output is suitable for a terminal through man and nroff, or for printing through troff. It does not install a page and it does not run a Perl program.

On current non-EBCDIC systems, the default output encoding is UTF-8. This is a version-sensitive detail: versions before Pod::Man 5.00 defaulted to the older roff encoding. Check your local tool before relying on a particular default:

$ dpkg-query -W -f='${Package} ${Version}\n' perl
perl 5.38.2-3.2ubuntu0.6
$ pod2man --help | sed -n '1,8p'
Usage:
    pod2man [--center=string] [--date=string] [--encoding=encoding]
    [--errors=style] [--fixed=font] [--fixedbold=font] [--fixeditalic=font]
    [--fixedbolditalic=font] [--guesswork=rule[,rule...]] [--name=name]
    [--nourls] [--official] [--release=version] [--section=manext]

1. Create a small POD source file

POD can live in its own .pod file or between Perl's =pod and =cut directives. Start with a separate file so the input and output are easy to inspect. The =encoding utf8 line declares the input encoding; it is independent of the output encoding selected later.

=encoding utf8

=head1 NAME

weather-report - print a short weather report

=head1 SYNOPSIS

weather-report [--city NAME]

=head1 DESCRIPTION

Prints a report for the requested city. If no city is supplied, the
program uses its configured default.

=head1 OPTIONS

=over 4

=item B<--city NAME>

Select the city to report.

=back

=head1 EXIT STATUS

The program returns zero when it prints a report and non-zero when the
request cannot be completed.

=cut

Keep a real program's POD close to the command's behaviour. Names, options and exit statuses in the documentation are not checked against your code by pod2man.

2. Generate a section 1 page

Give the input and output as two positional arguments. A section 1 suffix is conventional for a user command. The output is plain text containing macros such as .TH and .SH, so it is safe to review before installing anything.

$ pod2man --section=1 weather-report.pod weather-report.1
$ sed -n '1,18p' weather-report.1
.\" Automatically generated by Pod::Man 5.38.2
.\"
.nr rF 0
.if \n(.g .if rF .nr rF 1
.de Sp
.if t .sp .5v
.if n .sp
..
.de Vb
.ft CW
.nf
.ne \$1
..
.TH WEATHER-REPORT 1 "2026-09-26" "perl v5.38.2" "User Contributed Perl Documentation"
.SH NAME

The exact generated comments and date can vary. By default the date comes from POD_MAN_DATE, SOURCE_DATE_EPOCH, the input file's modification time, or the current date for standard input. Set --date when reproducible headers matter:

$ pod2man --section=1 --date=2026-09-26 weather-report.pod weather-report.1
$ grep '^\.TH' weather-report.1
.TH WEATHER-REPORT 1 "2026-09-26" "perl v5.38.2" "User Contributed Perl Documentation"

3. Read the result as a user would

Use man with the generated file before copying it into a system directory. The leading ./ matters because it tells man to open this file rather than search the installed manual path.

$ man ./weather-report.1
WEATHER-REPORT(1)     User Contributed Perl Documentation     WEATHER-REPORT(1)

NAME
    weather-report - print a short weather report

SYNOPSIS
    weather-report [--city NAME]

If you only need a non-interactive check, render through nroff and inspect the first lines:

$ nroff -man weather-report.1 | sed -n '1,24p'
WEATHER-REPORT(1)     User Contributed Perl Documentation     WEATHER-REPORT(1)

NAME
    weather-report - print a short weather report

4. Set useful headers deliberately

The page name is normally derived from the input filename and uppercased. Use --name when the filename is generic or when reading from standard input. Use --release for the project version and the centred-header option for a project header. These values are metadata in the .TH line, not content in the NAME section.

$ pod2man --name=weather-report --section=1 \
    --release=2.4.0 --center='Acme Tools' \
    --date=2026-09-26 weather-report.pod weather-report.1
$ grep '^\.TH' weather-report.1
.TH WEATHER-REPORT 1 "2026-09-26" "2.4.0" "Acme Tools"

--official changes the default centred header to indicate a standard Perl release, unless an explicit centred header is also given. It does not make a third-party command official, so leave it out for ordinary project documentation.

5. Choose encoding and error handling consciously

Use the default UTF-8 output for modern Linux systems. --encoding=roff is a compatibility option for old formatters and has poor results for many non-ASCII characters. It does not declare the input encoding. Keep =encoding utf8 in the POD when the source contains Unicode.

The default error style is die. A malformed POD document makes pod2man abort, normally with exit status 255. That is the safest choice in a build. --errors=stderr reports formatting errors but continues where possible; --errors=pod puts a POD ERRORS section in the generated page. Do not use those recovery modes as a substitute for fixing documentation.

$ pod2man --errors=die weather-report.pod weather-report.1
$ test -s weather-report.1 && echo 'man page generated'
man page generated

6. Handle scripts and multiple files

For a Perl script containing POD, pass the script as the input. pod2man extracts its documentation and does not execute the script. Add --name if standard input is involved, because the default name for standard input is STDIN.

$ pod2man --name=weather-report --section=1 bin/weather-report bin/weather-report.1

You can supply several input and output pairs in one invocation. Each pair is processed in order:

$ pod2man \
    --section=1 bin/weather-report bin/weather-report.1 \
    --section=5 conf/weather-report.conf.pod weather-report.conf.5

For a batch build, add --verbose to print each output filename. The command exits with status 1 if any document does not produce output. With default fatal POD error handling, a syntax error can stop processing earlier pairs, so check the exit status in your build script.

Common traps and safe boundaries

  • Do not overwrite an installed page while experimenting. Write to a temporary or project-local filename, then review it.
  • Installing under /usr/share/man/man1 requires elevated privileges and changes what other users see. Prefer a package build or a user-local manual path. If you deliberately copy a reviewed page there, remove that exact file to undo the change.
  • --utf8 is retained for compatibility but does nothing in current pod2man because UTF-8 is already the default on this platform.
  • --lax is also retained for compatibility and no longer validates a manual page. Use podchecker for POD validity, then use pod2man for conversion.
  • Default guesswork can format text that resembles Perl functions, variables or man-page references. Use --guesswork=none when documenting another language and want only explicit POD markup to control emphasis.

Done means

  • The source declares its input encoding when it contains non-ASCII text.
  • pod2man exits successfully and creates a non-empty .1 file.
  • man ./name.1 or nroff -man name.1 shows the expected NAME, SYNOPSIS and description sections.
  • The .TH line has the intended name, section, date, release and centred header.
  • No system manual directory was changed until the generated page was reviewed.