grog reads a roff file and hands you the exact groff command it needs, macros and preprocessors included. The examples use GNU grog 1.23.0 from the installed groff-base package, version 1.23.0-3build2. Allow about fifteen minutes. You need a shell, a readable roff input file, and the grog command itself. You do not need sudo, and running grog edits nothing and installs nothing.
Confirm which binary will run and record its version. These are read-only checks:
$ command -v grog
/usr/bin/grog
$ grog --version
GNU grog (groff) 1.23.0
$ dpkg-query -W groff-base
groff-base 1.23.0-3build2
The version matters because grog is an inference tool, not a complete roff parser. Its detection rules and the surrounding groff installation can change between releases.
Checkpoint: If command -v grog finds nothing, stop here and install the package through your normal system-management process. Do not copy a command from another machine and assume its preprocessors are installed locally.
Pass the input file as an operand. grog prints the inferred command; it does not format the document at this stage:
$ grog /path/to/document.roff
groff -ms /path/to/document.roff
The result depends on the document: ms macros typically produce groff -ms, a man page produces groff -man, and a table, equation or picture adds -t, -e or -p respectively. Treat the output as a proposed command, not a verdict, and read it before you run it.
For a small local test, create a file without touching any system path:
$ printf '.TH DEMO 1\n.SH NAME\ndemo \\- test\n.SH DESCRIPTION\nA small test.\n' > /tmp/demo.1
$ grog /tmp/demo.1
groff -man /tmp/demo.1
Here grog recognised the man macros straight from the file. Its output is plain text, so you can drop it into a shell script, a build rule or a review comment once you have checked the path and options.
Options placed before the file operand are copied straight into the inferred command, which matters when the output device or another groff setting is part of what you actually want:
$ grog -Tascii /tmp/demo.1
groff -Tascii -man /tmp/demo.1
The -- marker makes the boundary clear when a file name begins with a hyphen:
$ grog -Tascii -- /path/to/-draft.roff
-m just in case. grog normally detects macro packages itself, and a conflicting or inappropriate -m can make groff issue diagnostics; add one only after inspecting the source and finding the inference genuinely incomplete.-k. The grog manual advises giving groff this option so the preconv preprocessor can identify the encoding:$ grog -k -Tascii /path/to/utf8-document.roff
That does not convert the file or touch its encoding; it only changes the command grog proposes.
grog works by matching recognisable strings in the input. It does not recursively open every file named by a .so request, so a preprocessor used only in an included file can slip past it entirely.
Compare the direct inspection with a version passed through soelim first:
$ grog /path/to/top-level.roff
groff -ms /path/to/top-level.roff
$ soelim /path/to/top-level.roff | grog
groff -t -ms -
If the second result adds an option such as -t, the source tree probably needs soelim in the real build too. Check how your build handles included paths before turning this comparison into a permanent command; soelim is never added automatically just because a file contains .so.
With no file operand, or with an operand of -, grog reads standard input and represents it as - in the proposed command:
$ printf '.PP\nstdin test\n' | grog -
groff -ms -
Handy in pipelines, but remember the inferred command also expects its input from standard input. A command copied out and run later will not see the original pipeline unless you reproduce it or save the intermediate file.
--run writes the inferred command to standard error and then executes it. This is the point where output files, diagnostics and any shell-visible side effects from groff start to matter:
$ grog --run -Tascii /tmp/demo.1 > /tmp/demo.txt
$ head -n 8 /tmp/demo.txt
DEMO(1) General Commands Manual DEMO(1)
Check the inferred command first with ordinary grog. Do not run --run on untrusted input without considering included files, output paths and the groff options in your invocation. Shell redirection can truncate an existing destination before groff even starts, so write to a new or temporary file and rename it only after inspection.
The man page notes that groff's exit status is discarded when --run is used. If status matters for automation, run and check the printed command yourself rather than trusting a successful grog invocation as proof of a complete render.
Status 1 means grog thinks a macro package is in use but cannot tell which one. Status 2 means trouble handling an option or operand. Status 0 can also just mean no preprocessor or macro package was needed, which is not proof the input is valid or that the output looks right.
grog does not parse every roff control structure. Conditional requests, line continuations, changed control characters and some preprocessor regions can all hide the macros it is looking for. If the proposed command looks unexpectedly bare, inspect the source near those constructs and supply the missing groff option yourself. Keep the original file unchanged while you diagnose it.
soelim when hidden preprocessors were a risk.--run and shell redirection each got a destination review.