Your company here — click to reach over 10,000 unique daily visitors

podlinkcheck - Man Page

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.

Exit Status

Exit is 0 for no problems found, or non-zero for problems.

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 use Pod::Simple 3.24 up.

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, 2017 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/>.


2024-01-25 perl v5.38.2 User Contributed Perl Documentation