Submitting a tender, filing an application, archiving a project's documentation: in many cases documents must be delivered as PDF. Converting one file at a time with "Save As" is fine for three documents, not for sixty. LibreOffice, besides being a complete office suite, can work without a graphical interface, in "headless" mode, and convert whole groups of files with a single command. It works on Windows, macOS and Linux, and it is free.
The basic command
The program to call is soffice. On Windows it is usually in the C:\Program Files\LibreOffice\program\ folder; on Linux it is available directly in the terminal after installation.
soffice --headless --convert-to pdf --outdir C:\Delivery C:\Documents\*.docx
The options have precise meanings:
--headlessstarts LibreOffice without opening any windows;--convert-to pdfsets the target format;--outdirspecifies the folder where the results are saved;- the last argument lists the files to convert; wildcards such as
*.docxare handy, but how they are expanded depends on the terminal, so check the result the first time.
The output files keep their original names with a .pdf extension. The same command works with .doc, .odt, .rtf, .xlsx, .ods, .pptx and many other formats.
A frequent trap: LibreOffice already open
If LibreOffice is already running on the computer, perhaps with a document open, the command may finish without converting anything and without any explanation. The reason is that the new instance connects to the existing one and hands the job over to it. There are two solutions: close LibreOffice before launching the conversion, or specify a separate user profile with the -env:UserInstallation option, which makes the headless instance completely independent:
soffice -env:UserInstallation=file:///C:/Temp/lo_conversion --headless --convert-to pdf --outdir C:\Delivery C:\Documents\*.docx
In my work I always use a dedicated profile in automated scripts: it removes a whole category of malfunctions that are hard to diagnose.
Producing PDF/A
For long-term preservation and for many institutional portals, the PDF/A format is required. The export filter accepts additional options; in recent versions of LibreOffice they can be passed as JSON:
soffice --headless --convert-to "pdf:writer_pdf_Export:{\"SelectPdfVersion\":{\"type\":\"long\",\"value\":\"2\"}}" --outdir C:\Delivery document.docx
The value 2 corresponds to PDF/A-2b. The syntax is delicate, especially the quotation marks in different terminals, so it is worth testing it on your own version and checking the result with a PDF/A validator before automating an entire delivery. For spreadsheets the filter is called calc_pdf_Export and for presentations impress_pdf_Export.
A script for whole folders
A small Python script makes the conversion repeatable and handles subfolders, which wildcards alone do not:
import subprocess
from pathlib import Path
SOFFICE = r"C:\Program Files\LibreOffice\program\soffice.exe"
source = Path("C:/Project/Documents")
destination = Path("C:/Project/PDF")
extensions = {".docx", ".doc", ".odt", ".xlsx", ".ods", ".pptx"}
for file in sorted(source.rglob("*")):
if file.suffix.lower() not in extensions or file.name.startswith("~$"):
continue
folder = destination / file.parent.relative_to(source)
folder.mkdir(parents=True, exist_ok=True)
subprocess.run(
[SOFFICE, "--headless", "--convert-to", "pdf",
"--outdir", str(folder), str(file)],
check=True, timeout=180,
)
Two practical details. Files starting with ~$ are temporary files created by Word while a document is open: they must be skipped. The timeout parameter stops a problematic document from blocking the script forever.
Conversion fidelity
LibreOffice opens Microsoft formats with very good, but not always identical, compatibility. The most common differences concern:
| Element | Possible problem | Remedy |
|---|---|---|
| Fonts | Missing fonts replaced by others | Install the same fonts on the converting computer |
| Layout | Page breaks slightly shifted | Check long documents |
| Spreadsheets | No print area defined, columns split across pages | Set the print area and fit-to-page in the original file |
| Fields | Dates or tables of contents not updated | Update fields before converting |
Spreadsheets deserve particular attention: conversion follows the file's print settings. If no print area is defined, a wide sheet can become a PDF of dozens of pages with just a few columns each.
When to use other tools
On a computer with Microsoft Office installed, conversion can also be done by driving Word itself from a script, with perfect fidelity to Word documents. It is slower, however, needs a licence and doesn't work on Linux servers. For conversions between text formats such as Markdown, HTML and Word, a tool like Pandoc is a better fit.
In short
soffice --headless --convert-to pdfconverts whole groups of documents to PDF.- Use a dedicated profile with
-env:UserInstallationto avoid clashes with an open LibreOffice. - PDF/A is obtained through export filter options, to be tested on your own version.
- A Python script handles subfolders, temporary files and time limits.
- Install the same fonts and define print areas for faithful conversions.