podlinkcheck man page

podlinkcheck -- check Perl pod L<> link references


podlinkcheck [--options] file-or-dir...


The command line options are

Print a command line summary.
-I dir
Add an extra directory to look for target modules.
Print more about program operation (including CPAN loading).
Print the program version number and exit.


PodLinkCheck parses Perl POD from a script, module or documentation and checks that "L<>" links within it refer to a known program, module, or man page.

L<foo>          check module, pod or program "foo"
L<foo/section>    and check section within the pod
L<bar(1)>       check man page "bar(1)"

The command line is either individual files or whole directories. For a directory all the .pl, .pm and .pod files under it are checked. So for example to churn through all installed add-on modules,

podlinkcheck /usr/share/perl5

Bad links are usually typos in the module name or section name, or sometimes "L<display|target>" parts the wrong way around. Occasionally there may be an "L<foo>" used where just markup "C<>" or "I<>" was intended.


External links are checked by seeking the target .pm module or .pod documentation in the @INC path (per Pod::Find), or seeking a script (no file extension) in the usual executable "PATH". A section name in a link is checked by parsing the POD in the target file.

If a module is not installed in @INC or extra "-I" directories then its existence is also checked in the CPAN indexes with "App::cpanminus", "CPAN::SQLite", "CPAN" or "CPANPLUS". Nothing is downloaded, just current data consulted. A warning is given if a section name in a link goes unchecked because it's on CPAN but not available locally.

If checking your own work then most likely you will have copies of cross-referenced modules installed (having compared or tried them). In that sense the CPAN index lookups are a fallback.

Manpage links are checked by asking the "man" program if it recognises the name, including any number part like chmod(2). A manpage can also satisfy what otherwise appears to be a POD link with no sub-section, since there's often some confusion between the two.

Section Name Matching

An "L<>" section name can use just the first word of an item or heading. This is how "Pod::Checker" behaves and it's good for "perlfunc" cross references where just the function name can be given without the full argument list of the "=item". Eg.


The first word is everything up to the first whitespace. This doesn't come out very well on a target like "=item somefun( ARG )", but it's how "Pod::Checker" 1.45 behaves. If the targets are your own then you might make the first word or full item something sensible to appear in an "L<>".

If a target section is not found then "podlinkcheck" will try to suggest something close, eg. differing only in punctuation or upper/lower case. Some of the POD translators may ignore upper/lower case anyway, but it's good to write an "L<>" the same as the actual target.

foo.pl:130:31: no section "constructor" in "CHI"
  (file /usr/share/perl5/CHI.pm)
  perhaps it should be "CONSTRUCTOR"

For reference, numbered "=item" section names go in an "L<>" without the number. This is good since the numbering might change. If "podlinkcheck" suggests a number in a target then it may be a mistake in the target document. A numbered item should have the number alone on the "=item" and the section name as the next paragraph.

=item 1.                        # good
The First Thing                 # the section name
Paragraph about this thing.
=item 2. The Second Thing       # bad
Paragraph about this next thing.

The second item "2. The Second Thing" is not a numbered item for POD purposes, but rather text that happens to start with a number. Of course sometimes that's what you want, eg.

=item 64 Bit Support

"podlinkcheck" uses "Pod::Simple" for parsing and so follows its interpretation of the various hairy "L<>" link forms. If an "L<>" appears to be mis-interpreted you might rewrite or add some escapes (like E<sol>) for the benefit of all translators which use "Pod::Simple". In Perl 5.10 that includes the basic "pod2man".

Other Ways to Do It

"podchecker" (the "Pod::Checker" module) checks internal links, but it doesn't check external links.

"Test::Pod::LinkCheck" is similar in a .t test framework. It uses some of PodLinkCheck but different reporting and a stricter approach to dubious POD.

Environment Variables

The search path for installed scripts.
Used by the various "CPAN" modules for "~/.cpan" etc directories.
The usual extra Perl module directories (see "ENVIRONMENT" in perlrun), which become @INC where link targets are sought.


"App::cpanminus" is checked first since it's a bsearch of 02packages.details.txt, and "CPAN::SQLite" second since it's a database lookup. But if a target is not found there then the full "CPAN" and "CPANPLUS" caches are loaded and checked. This might use a fair bit of memory for a non-existent target, but it's also possible they're more up-to-date.

No attempt is made to tell which of the indexes is the most up-to-date. If a module has been renamed (bad) then it may still exist in an old index. The suggestion is to avoid having old stuff lying around (including old mirror files in "App::cpanminus").

The code consulting "CPAN.pm" may need a tolerably new version of that module, maybe 1.61 circa Perl 5.8.0. On earlier versions its index is not used.

The line:column number reported for an offending "L<>" is found by some gambits extending what "Pod::Simple" normally records. There's a chance it could be a little off within the paragraph.

"Pod::Simple" prior to version 3.24 didn't allow dots "." in man-page names, resulting in for example login.conf(5) being treated as a Perl module name not a man page name. If you have such links then "Pod::Simple" 3.24 up is recommended.

Directories are currently traversed using File::Find::Iterator. It follows symlinks but neither its version 0.4 nor PodLinkCheck guard against infinite descent into symlink cycles. The intention perhaps would be follow all symlinks to files, but follow to a directory just once as protection against cycles.


~/.cpanm/sources/*/02packages.details.txt files from "App::cpanminus"

~/.cpan/cpandb.sql used by "CPAN::SQLite"

~/.cpan/Metadata used by "CPAN"

~/.cpanplus/* variously used by "CPANPLUS"

See Also

podchecker, podlint

Pod::Simple, Pod::Find, CPAN, CPAN::SQLite, CPANPLUS, cpanm

Test::Pod::LinkCheck, Pod::Checker, Test::Pod

Home Page



Copyright 2010, 2011, 2012, 2013, 2016 Kevin Ryde

PodLinkCheck is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

PodLinkCheck is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with PodLinkCheck. If not, see <http://www.gnu.org/licenses/>.


Explore man page connections for podlinkcheck(1).