Inspect Man Page Headers and Filters with lexgrog
A man page that will not show up in whatis or apropos almost always has a broken NAME section, and lexgrog is the tool that tells you exactly that. You will check a page's parsed name and description, see which preprocessors it needs, and tell a malformed page apart from a bad invocation. The examples use man-db 2.12.0, installed here as package version 2.12.0-4build2. Allow about ten minutes. You need a shell and a readable man page source or preformatted cat page. These checks are read-only and do not need sudo.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Check the installed command
Start by checking which executable will run and which release it reports:
$ command -v lexgrog
/usr/bin/lexgrog
$ lexgrog --version
lexgrog 2.12.0
The man page describes lexgrog as a parser for header information in man pages. It accepts one or more files, and a file named - means standard input. Compressed input is decompressed automatically, so an installed .gz man page can be passed straight through.
Checkpoint
If command -v finds nothing, install man-db through your normal package manager before continuing. Do not diagnose a missing executable as a parsing failure.
2. Read the NAME data that whatis uses
With no mode options, lexgrog defaults to parsing man source and printing whatis information. Point it at the installed lexgrog page itself:
$ lexgrog /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz: "lexgrog - parse header information in man pages"
The result comes straight from the page's NAME section: the name and short description that apropos and whatis index. A successful parse does not validate the rest of the document, and it does not prove the examples inside it actually work.
Pass several files for a batch check. Each gets its own result, which makes a quick scan easy:
$ lexgrog /usr/share/man/man1/lexgrog.1.gz /usr/share/man/man1/man.1.gz
/usr/share/man/man1/lexgrog.1.gz: "lexgrog - parse header information in man pages"
/usr/share/man/man1/man.1.gz: "man - an interface to the system reference manuals"
3. Inspect the preprocessing filters
Use --filters to see which preprocessing pipeline lexgrog has inferred, combined with --whatis to keep the description too:
$ lexgrog --filters --whatis /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz (-): "lexgrog - parse header information in man pages"
The parenthesised marker is the filter result for this page. A page using requests such as .tbl, .eqn or .pic can produce a different marker. Treat this as a diagnostic hint about the page's source, not a command line to copy straight into nroff without checking the page and your formatter first.
Drop --whatis if you only want the filter information:
$ lexgrog --filters /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz (-)
4. Choose man source or cat-page parsing explicitly
The default is --man, for roff source. Use --cat only when the input is already a preformatted cat page:
$ lexgrog --man /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz: "lexgrog - parse header information in man pages"
--man and --cat are alternatives, not modes you stack together; supplying both is a usage error. A cat page is not simply man source with a different extension, so match the mode to the actual content. If unsure, check the file's origin and try the default first.
5. Check a page in a script
For automation, the exit status is more reliable than matching wording. The documented statuses are 0 for success, 1 for a usage error, and 2 when lexgrog could not parse one or more inputs:
lexgrog --man /path/to/page.1.gz
status=$?
case "$status" in
0) printf '%s\n' 'man page parsed' ;;
1) printf '%s\n' 'lexgrog usage error' >&2; exit 1 ;;
2) printf '%s\n' 'man page parse failed' >&2; exit 2 ;;
*) printf 'unexpected lexgrog status %s\n' "$status" >&2; exit 1 ;;
esac
For a broken page, the normal whatis output includes parse failed. Capture the status immediately after lexgrog runs, since any later command overwrites $?. Keep the input path in the report so a batch check identifies exactly which file failed.
6. Fix the NAME section at its source
When the parser fails, inspect the source instead of reaching for random flags. Traditional man macros put the command name and its short description in a .SH NAME section, with the name, a literal escaped hyphen, then the description:
.SH NAME
tool \- inspect an example file
- Several names can be comma-separated.
- Separate descriptions can use a break or paragraph request.
- BSD-derived mdoc pages differ: they use
.Sh NAME,.Nmand.Ndinstead. - Names containing whitespace are ignored, because accepting them could produce unsafe or misleading whatis entries.
Warning
Do not rename a section merely to make a check pass. A section called .SH MYPROGRAM, or free-form text with no name and description, can leave mandb without the data it needs. After editing a page, rerun lexgrog against the exact installed or staged file and check the exit status again.
Common traps
- Use
--manfor source,--catfor preformatted output. They cannot be combined. - Use
--encodingonly when the guessed character set is wrong. It changes decoding, not NAME syntax. .sorequests only resolve correctly when installed in a proper manual-page hierarchy.- Skip
sudofor a readable page. Elevated access only matters if filesystem permissions block reading the input. - Never overwrite a packaged page while testing a fix. Work on a copy in a writable directory, then install it through your normal packaging or deployment workflow if that is genuinely required.
Done means
- Version confirmed:
lexgrog --versionreports the expected installed release. - NAME data checked: the target page returns its expected description with the default mode.
- Filters inspected: checked with
--filtersand read as diagnostics, not commands to copy. - Scripts branch correctly: on status 0, 1 and 2, without losing
$?. - Fixes land in the right place: a parse failure gets repaired in the page's NAME section, never hidden behind an unrelated option.