11. Kommandozeile
← Standardbibliothek · Inhalt · Weiter: Rezepte →
Zwölf Befehle: vier für PDFs, vier für Skripte, zwei für die Verteilung und zwei für die Lizenzierung.
| Befehl | Zweck |
|---|---|
run |
Prüft ein PDF mit einem Skript |
compare |
Vergleicht zwei Fassungen |
watch |
Überwacht einen Ordner und prüft, was eintrifft |
fix |
Wendet Änderungen an und speichert ein neues PDF |
inspect |
Schneller Überblick über ein PDF |
lint |
Analysiert ein Skript, ohne es auszuführen |
fmt |
Formatiert ein Skript |
doc |
Erzeugt die Dokumentation eines Skripts |
pack |
Packt Profile und Daten |
add |
Installiert ein Paket |
fingerprint |
Geräte-Fingerabdruck |
license |
Lizenzprüfung |
Exit-Codes
Gelten für alle Befehle, die prüfen.
| Code | Bedeutung |
|---|---|
0 |
Alles bestanden |
1 |
Nur Warnungen |
2 |
Prüffehler oder PDF nicht lesbar |
3 |
Syntaxfehler im Skript |
pdfl run profil.pdfl datei.pdf > bericht.json
case $? in
0) echo "approved" ;;
1) echo "approved with warnings" ;;
2) echo "rejected — see bericht.json" ;;
3) echo "error in the validation script" ;;
esac
pdfl run
Prüft ein PDF mit einem Skript.
pdfl run <skript.pdfl> <eingabe.pdf> [optionen]
| Option | Vorgabe | Zweck |
|---|---|---|
--output json|csv|html|pdf |
json |
Format des Berichts |
--output-file <datei> |
— | Schreibt in eine Datei statt auf die Standardausgabe |
--fail-on error|warning |
error |
Mit warning führt auch eine Warnung zu Code 2 |
--verbose |
— | Zusatzinformationen auf der Fehlerausgabe |
pdfl run vorstufe.pdfl magazin.pdf # JSON im Terminal
pdfl run vorstufe.pdfl magazin.pdf --output html --output-file bericht.html
pdfl run vorstufe.pdfl magazin.pdf --output pdf --output-file bericht.pdf
pdfl run vorstufe.pdfl magazin.pdf --output csv --output-file befunde.csv
pdfl run vorstufe.pdfl magazin.pdf --fail-on warning # strenger Modus
Der JSON-Bericht
{
"script_name": "prepress.pdfl",
"input_file": "magazine.pdf",
"profile": "offset-magazine",
"status": "FAIL",
"total_pages_analyzed": 120,
"error_count": 2,
"warning_count": 0,
"info_count": 0,
"diagnostics": [
{
"id": "PDFL-001",
"severity": "error",
"check_name": "Ink coverage",
"message": "page 7: 324% ink (limit 300%)",
"line": 12
}
]
}
Dasselbe PDF mit demselben Skript ergibt stets einen Byte für Byte identischen Bericht: Man kann ihn versionieren und Unterschiede in der CI vergleichen.
pdfl compare
Vergleicht zwei Fassungen: Text, Struktur und Metadaten.
pdfl compare <v1.pdf> <v2.pdf> [optionen]
| Option | Vorgabe | Zweck |
|---|---|---|
--output json|csv|html|pdf |
json |
Format |
--output-file <datei> |
— | Schreibt in eine Datei |
--normalize |
— | Ignoriert Groß-/Kleinschreibung und Leerzeichen |
--ignore-dates |
— | Maskiert Datumsangaben vor dem Vergleich |
--similarity-threshold <0-100> |
100 |
Kleinste hinnehmbare Ähnlichkeit |
pdfl compare freigegeben_v1.pdf erhalten_v2.pdf --normalize --ignore-dates
# Bis zu 1 % Abweichung ist erlaubt; darunter ist es ein Fehler
pdfl compare v1.pdf v2.pdf --similarity-threshold 99 \
--output html --output-file unterschiede.html
Wie es arbeitet
- Seiten werden nach Inhalt einander zugeordnet, nicht nach Nummer: Eine in der Mitte eingefügte Seite lässt nicht alles Folgende als Unterschied erscheinen. Funktioniert auch bei mehr als tausend Seiten.
- Jedes Paar bekommt einen Ähnlichkeitswert und eine Auswahl der geänderten
Zeilen (
-entfernt,+ergänzt). - Eine Änderung der Metadaten ist eine Warnung; eine Textänderung unter der Schwelle ist ein Fehler, darüber eine Warnung.
- Der Gesamtwert steht im Feld
similaritydes Berichts.
page 4 → 4: similarity 97.8% | -original title | +revised title
pdfl watch
Überwacht einen Ordner und prüft jedes PDF, das eintrifft oder sich ändert.
pdfl watch <ordner> --script <skript.pdfl> [optionen]
| Option | Vorgabe | Zweck |
|---|---|---|
--pattern <glob> |
*.pdf |
Welche Dateien verarbeitet werden |
--exclude <glob> |
— | Welche übergangen werden |
--output-dir <ordner> |
neben dem PDF | Wohin die Berichte gehen |
--depth <n> |
1 |
Tiefe der Unterordner |
--debounce <ms> |
1000 |
Wartezeit, bis die Datei stabil ist |
--report json|csv|html|pdf |
json |
Format der Berichte |
--fail-fast |
— | Hält beim ersten Fehler an |
--once |
— | Verarbeitet den Bestand und beendet sich |
# Eingangsordner einer Druckerei, im Dauerbetrieb
pdfl watch inbox/ --script preflight.pdfl --output-dir berichte/ --report html
# Stapellauf für die CI: beendet sich mit dem schlechtesten Code
pdfl watch inbox/ --script preflight.pdfl --once
echo "result: $?"
Das debounce gibt es, weil große Dateien in Stücken ankommen: Verarbeitet wird nur eine Datei, die sich nicht mehr ändert — also nie ein halb geschriebenes PDF.
Die Berichte entstehen als <name>.report.json (oder .csv, .html, .pdf).
pdfl fix
Wendet die fix::-Operationen an und speichert ein neues PDF. Einzelheiten in
Kapitel 8.
pdfl fix original.pdf normalisieren.pdfl --output out.pdf --dry-run # nur ansehen
pdfl fix original.pdf normalisieren.pdfl --output korrigiert.pdf # anwenden
pdfl inspect
Überblick über ein PDF, ohne Skript.
pdfl inspect <datei.pdf>
File: magazine.pdf
Size: 26 KB (27284713 bytes)
SHA-256: af1029842e5bfeae338ead82fb449ef851be742b1d63117c12596e3ea123a616
Pages: 120
Page size: 496 x 709 pt
Boxes: MediaBox, TrimBox, BleedBox
Metadata:
Title: Example Magazine
Creator: Adobe InDesign 19.3
Fonts: 26
ABCDEF+Helvetica — embedded
Arial — NOT embedded
Images: 81 (minimum DPI 136, spaces: DeviceCMYK, Indexed)
Max. estimated TAC: 300% (RGB render approximation)
Warnings:
! there are non-embedded fonts
! 3 image(s) below 300 DPI
Der erste Befehl, wenn eine Datei eintrifft: In Sekunden weiß man, ob sie das Öffnen lohnt.
pdfl lint
Analysiert ein Skript, ohne es auszuführen, und meldet Qualitätsprobleme.
pdfl lint <skript.pdfl>
Was es findet:
- Variablen, Blockparameter und Funktionen, die deklariert und nie benutzt
werden (mit
_davor lässt sich die Warnung unterdrücken:_page) - Doppelte oder leere checks
- Unbekannte Namensräume (
text::,struct::,visual::,prepress::,codes::,fix::,data::) assert/requireaußerhalb eines checks- Gebrauch von
fix::(läuft nur unterpdfl fix)
$ pdfl lint profil.pdfl
profil.pdfl: warning: variable 'LIMIT' declared and never used
profil.pdfl: warning: check "Fonts" declared 2 times
Bei Warnungen ist der Exit-Code 1 — in der CI verwendbar.
pdfl fmt
Formatiert ein Skript: zwei Leerzeichen Einrückung, einheitliche Abstände,
zusammengefasste Leerzeilen. Kommentare und Einheiten (3mm bleibt 3mm)
bleiben erhalten.
pdfl fmt <skript.pdfl> # formatiert an Ort und Stelle
pdfl fmt <skript.pdfl> --check # ändert nichts; Code 1, wenn unformatiert
# Teamstandard in der CI durchsetzen
for f in profile/*.pdfl; do pdfl fmt "$f" --check || exit 1; done
pdfl doc
Erzeugt die Dokumentation aus dem Skript selbst.
pdfl doc <skript.pdfl> [--output markdown|html]
Ausgegeben werden: das Profil, eine Tabelle der Konstanten, die Funktionen, die
Importe und zu jedem check seine Etiketten und das, was er prüft (die Meldungen
der assert werden zu den Beschreibungen).
pdfl doc vorstufe.pdfl > docs/vorstufen-profil.md
pdfl doc vorstufe.pdfl --output html > profil.html
Das ist das Ergebnis, das einer Produktionsleitung, die keinen Code liest, erklärt, was ein Profil prüft.
pdfl pack
Packt Skripte und Daten in ein verteilbares .pdflpkg.
pdfl pack <ordner> [--name <name>] [--version <version>] [--output <datei>]
Es sammelt rekursiv die .pdfl-, .csv-, .txt-, .json- und
.xlsx-Dateien des Ordners und legt ein manifest.json bei, das den SHA-256
jeder Datei notiert. Das Packen ist deterministisch: Derselbe Ordner ergibt
dieselben Bytes.
pdfl pack profile/druckerei --name druckprofil --version 1.0.0
pdfl add
Installiert ein lokales Paket und prüft dabei die Prüfsummen des Manifests.
pdfl add druckprofil.pdflpkg
# installiert nach ./pdfl_profiles/druckprofil@1.0.0/
pdfl run pdfl_profiles/druckprofil@1.0.0/vorstufe.pdfl datei.pdf
Stimmt die Prüfsumme einer Datei nicht, wird die Installation verweigert — ein beschädigtes oder verändertes Paket kommt nicht hinein.
Ferne Verzeichnisse und digitale Signaturen gehören nicht zu dieser Version:
addinstalliert aus einer lokalen Datei.
pdfl fingerprint
Der Fingerabdruck dieses Rechners — der Wert, den Sie an Ihren Anbieter schicken, um eine Lizenz zu erhalten.
pdfl fingerprint generate
Er wird allein auf die Standardausgabe geschrieben; der erklärende Text geht auf
die Fehlerausgabe, pdfl fingerprint generate 2>/dev/null liefert also einen
Wert, der sich direkt weiterleiten lässt.
$ pdfl fingerprint generate
Device fingerprint for this machine:
1a7553e711c53306be083ea8927c9cbe
Send it to your vendor to be issued a license.
It changes if the operating system is reinstalled.
Der Fingerabdruck stammt aus der Maschinenkennung des Systems (
/etc/machine-id,IOPlatformUUIDoderMachineGuid). Eine Neuinstallation des Systems überlebt er nicht, und aus demselben Abbild geklonte virtuelle Maschinen teilen sich den Wert. Für CI und Container — wo der Rechner bei jedem Lauf verworfen wird — gibt es dieseatless-Lizenz, die nicht auf das Gerät schaut.
pdfl license
Prüft eine erhaltene Lizenz. pdfl prüft nur: ausgestellt werden Lizenzen
vom Anbieter, mit dem privaten Schlüssel, der nicht mit der Binärdatei
ausgeliefert wird.
pdfl license check <token>
$ pdfl license check "$(cat license.txt)"
signature: ok
customer: Example Print Shop
expires: 2027-01-01
features: all
device: 1a7553e711c53306be083ea8927c9cbe
this machine: matches
Beendet sich mit 0, wenn die Lizenz für diesen Rechner gilt, sonst mit 2 —
auch dann, wenn die Signatur stimmt, die Lizenz aber zu einem anderen Rechner
gehört; in dem Fall sagt die Meldung genau das.
| Option | Zweck |
|---|---|
--pubkey <base64> |
Zu verwendender öffentlicher Schlüssel statt des einkompilierten |
Wo eine Lizenz verlangt wird
run, fix, watch, compare und inspect halten mit Code 2 an, wenn es
für diesen Rechner keine gültige Lizenz gibt. fingerprint generate verlangt nie eine —
es erzeugt ja gerade den Wert, mit dem man eine anfordert. lint, fmt, doc
und pack fassen nur Skripte an, nie ein PDF, und verlangen ebenfalls keine.
Das Token wird in dieser Reihenfolge gesucht:
$PDFL_LICENSE— der Weg für die CI, wo es zum Secret wird~/.config/pdfl/licensepdfl.licenseneben der ausführbaren Datei
$ pdfl run profil.pdfl datei.pdf
error: no license found
Run 'pdfl fingerprint generate' and send the value to your vendor
to be issued a license. Then set PDFL_LICENSE, or save the token to
/home/sie/.config/pdfl/license.
Eine
seatless-Lizenz hat eine Laufobergrenze, gezählt in~/.config/pdfl/state. Dieselbe Datei hält fest, wann zuletzt gelaufen wurde, und verweigert den Lauf, wenn die Uhr zurückgestellt wird — mit einer Stunde Toleranz, damit die Zeitsynchronisation nicht dazwischenfunkt.