| name | pdf-to-report-workflow |
| description | Complete PDF workflow: extract content from source PDFs and generate new PDF reports using command-line tools |
PDF-to-Report Generation Workflow
This skill provides a complete end-to-end workflow for processing PDF documents: extracting content from source PDFs, assembling report data, and generating new PDF output files—all using command-line tools when Python libraries are unavailable.
When to Use This Skill
- Need to extract text/content from existing PDFs
- Need to create new PDF reports from extracted data
- Need to combine multiple PDF sources into a single report
- PyPDF2, reportlab, or similar Python PDF libraries are unavailable
- Working in minimal/containerized environments
Core Tools
Extraction Tools (poppler-utils)
1. pdfinfo - Extract PDF Metadata
pdfinfo document.pdf
pdfinfo document.pdf | grep Pages
pdfinfo document.pdf | grep Pages | awk '{print $2}'
Key metadata fields:
Pages: Number of pages in the PDF
Title: Document title
Author: Document author
CreationDate: When the PDF was created
ModDate: Last modification date
2. pdftotext - Extract Text Content
pdftotext document.pdf -
pdftotext document.pdf output.txt
pdftotext -f 1 -l 3 document.pdf output.txt
pdftotext -layout document.pdf output.txt
Generation Tools (Choose based on availability)
1. enscript + ps2pdf - Text to PDF (Recommended)
Convert plain text to PDF via PostScript:
apt-get install -y enscript ghostscript
enscript -B -o output.ps input.txt && ps2pdf output.ps output.pdf
enscript -B input.txt -o - | ps2pdf - output.pdf
Options:
-B: No borders
-o: Output file (- for stdout)
-f: Font specification (e.g., -fCourier10)
2. wkhtmltopdf - HTML to PDF
Convert HTML to PDF with full formatting support:
apt-get install -y wkhtmltopdf
wkhtmltopdf input.html output.pdf
echo "<html><body><h1>Report</h1></body></html>" | wkhtmltopdf - output.pdf
wkhtmltopdf --page-size A4 --margin-top 25mm input.html output.pdf
3. libreoffice - Document Conversion
Convert various document formats to PDF:
apt-get install -y libreoffice-writer
libreoffice --headless --convert-to pdf input.docx
libreoffice --headless --convert-to pdf input.odt
libreoffice --headless --convert-to pdf input.txt
4. pandoc - Universal Document Converter
Convert between many formats including PDF:
apt-get install -y pandoc texlive-latex-base
pandoc input.md -o output.pdf
pandoc input.txt -o output.pdf
pandoc input.md --template=template.tex -o output.pdf
5. pdftk - PDF Manipulation
Merge, split, or modify existing PDFs:
apt-get install -y pdftk
pdftk file1.pdf file2.pdf file3.pdf cat output merged.pdf
pdftk input.pdf cat 1-3 output extracted.pdf
pdftk input.pdf burst
Complete Workflow
Phase 1: Check Tool Availability
which pdfinfo || echo "pdfinfo not found"
which pdftotext || echo "pdftotext not found"
which enscript || echo "enscript not found"
which wkhtmltopdf || echo "wkhtmltopdf not found"
which libreoffice || echo "libreoffice not found"
which pandoc || echo "pandoc not found"
Phase 2: Install Missing Tools
apt-get update && apt-get install -y poppler-utils enscript ghostscript
apt-get install -y poppler-utils wkhtmltopdf
apt-get install -y poppler-utils pandoc texlive-latex-base
Phase 3: Extract Content from Source PDFs
mkdir -p workdir/extracted
cd workdir
for pdf in ../source_pdfs/*.pdf; do
filename=$(basename "$pdf" .pdf)
pdftotext -layout "$pdf" "extracted/${filename}.txt"
echo "Extracted: $filename"
done
for txt in extracted/*.txt; do
lines=$(wc -l < "$txt")
echo "$txt: $lines lines"
done
Phase 4: Assemble Report Content
cat > final_report.txt << 'EOF'
===========================================
NEW CASE CREATION REPORT
Generated: $(date)
===========================================
EOF
echo "SECTION 1: CASE CREATION GUIDE" >> final_report.txt
echo "-------------------------------------------" >> final_report.txt
cat extracted/case_creation_guide.txt >> final_report.txt
echo "" >> final_report.txt
echo "SECTION 2: CASE DETAIL SUMMARY" >> final_report.txt
echo "-------------------------------------------" >> final_report.txt
cat extracted/case_detail_summary.txt >> final_report.txt
echo "" >> final_report.txt
echo "SECTION 3: PATERNITY TEST RESULTS" >> final_report.txt
echo "-------------------------------------------" >> final_report.txt
cat extracted/paternity_test_results.txt >> final_report.txt
echo "" >> final_report.txt
echo "SECTION 4: ORDER OF CHILD SUPPORT" >> final_report.txt
echo "-------------------------------------------" >> final_report.txt
cat extracted/order_of_child_support.txt >> final_report.txt
echo "" >> final_report.txt
echo "===========================================" >> final_report.txt
echo "END OF REPORT" >> final_report.txt
echo "===========================================" >> final_report.txt
Phase 5: Generate PDF Report
Option A: Using enscript + ps2pdf
enscript -B -fCourier10 -o report.ps final_report.txt && ps2pdf report.ps final_report.pdf
enscript -B final_report.txt -o - | ps2pdf - final_report.pdf
pdfinfo final_report.pdf | grep Pages
Option B: Using wkhtmltopdf (with HTML formatting)
cat > final_report.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: monospace; margin: 40px; }
h1 { text-align: center; }
.section { margin-top: 30px; }
</style>
</head>
<body>
EOF
sed 's/&/\&/g; s/</\</g; s/>/\>/g' final_report.txt | \
sed 's/^=\{30,\}/<h1>/; s/$/<\/h1>/; /^<h1>/!s/^/--<br>/; /^----/!s/$/<br>/' >> final_report.html
echo "</body></html>" >> final_report.html
wkhtmltopdf --page-size A4 --margin-top 25mm final_report.html final_report.pdf
Option C: Using pandoc (markdown format)
cat > final_report.md << 'EOF'
*Generated: $(date)*
---
EOF
for txt in extracted/*.txt; do
filename=$(basename "$txt" .txt)
echo "## $filename" >> final_report.md
echo "" >> final_report.md
cat "$txt" >> final_report.md
echo "" >> final_report.md
done
pandoc final_report.md -o final_report.pdf
Phase 6: Verify Generated Report
if [ -f final_report.pdf ]; then
echo "✓ PDF created successfully"
pages=$(pdfinfo final_report.pdf | grep Pages | awk '{print $2}')
echo " Pages: $pages"
size=$(ls -lh final_report.pdf | awk '{print $5}')
echo " Size: $size"
if pdftotext final_report.pdf - | grep -q "CASE CREATION REPORT"; then
echo "✓ Content verified"
else
echo "✗ Content verification failed"
fi
else
echo "✗ PDF generation failed"
exit 1
fi
Python Integration Example
import subprocess
import os
from datetime import datetime
class PDFReportGenerator:
def __init__(self, workdir="workdir"):
self.workdir = workdir
os.makedirs(workdir, exist_ok=True)
os.makedirs(f"{workdir}/extracted", exist_ok=True)
def check_tools(self):
"""Check available tools and return best option"""
tools = {}
for tool in ['pdfinfo', 'pdftotext', 'enscript', 'ps2pdf',
'wkhtmltopdf', 'pandoc']:
result = subprocess.run(['which', tool],
capture_output=True, text=True)
tools[tool] = result.returncode == 0
return tools
def extract_pdf(self, pdf_path, output_txt=None):
"""Extract text from PDF"""
if output_txt is None:
output_txt = f"{self.workdir}/extracted/{os.path.basename(pdf_path).replace('.pdf', '.txt')}"
result = subprocess.run(
['pdftotext', , pdf_path, output_txt],
capture_output=, text=
)
result.returncode != :
Exception()
output_txt
():
tools = .check_tools()
temp_txt =
(temp_txt, ) f:
f.write(text_content)
tools.get() tools.get():
temp_ps =
subprocess.run([, , , , temp_ps, temp_txt], check=)
subprocess.run([, temp_ps, output_pdf], check=)
output_pdf
tools.get():
temp_md =
(temp_md, ) f:
f.write()
f.write(text_content)
subprocess.run([, temp_md, , output_pdf], check=)
output_pdf
tools.get():
temp_html =
(temp_html, ) f:
f.write()
subprocess.run([, temp_html, output_pdf], check=)
output_pdf
:
Exception()
():
result = subprocess.run([, pdf_path],
capture_output=, text=)
info = {}
line result.stdout.split():
line:
key, value = line.split(, )
info[key.strip()] = value.strip()
info
():
extracted_texts = []
pdf source_pdfs:
txt = .extract_pdf(pdf)
(txt, ) f:
content = f.read()
extracted_texts.append((os.path.basename(pdf), content))
report_content =
filename, content extracted_texts:
report_content +=
report_content +=
report_content +=
report_content += content +
report_content +=
.generate_report_pdf(report_content, output_pdf)
__name__ == :
generator = PDFReportGenerator()
source_pdfs = [
,
,
,
]
output = generator.create_report_from_pdfs(
source_pdfs,
,
)
()
()
Common Workflows
| Task | Command Sequence |
|---|
| Extract single PDF | pdftotext -layout file.pdf output.txt |
| Extract multiple PDFs | for f in *.pdf; do pdftotext -layout "$f" "${f%.pdf}.txt"; done |
| Text to PDF (enscript) | enscript -B input.txt -o - | ps2pdf - output.pdf |
| Text to PDF (pandoc) | pandoc input.md -o output.pdf |
| Merge PDFs | pdftk file1.pdf file2.pdf cat output merged.pdf |
| Verify PDF | pdfinfo file.pdf | grep Pages |
| Check PDF content | pdftotext file.pdf - | grep -i "keyword" |
Troubleshooting
No PDF generation tools available
- Install at least one:
apt-get install enscript ghostscript (simplest)
- Or:
apt-get install pandoc texlive-latex-base (best formatting)
- Or:
apt-get install wkhtmltopdf (HTML support)
enscript produces garbled output
- Check character encoding:
file input.txt
- Try adding
-r option for raw output
- Use
-fCourier10 for fixed-width font
ps2pdf produces large files
- Add compression:
ps2pdf -dPDFSETTINGS=/ebook input.ps output.pdf
- Or:
ps2pdf -dPDFSETTINGS=/screen input.ps output.pdf (smaller, lower quality)
pdftotext returns empty output
- PDF may be image-only (scanned) - requires OCR tools
- PDF may be encrypted/password-protected
- Try
pdftotext -layout for better extraction
Report formatting looks poor
- Use
pandoc with markdown for better formatting
- Use
wkhtmltopdf with HTML/CSS for full control
- Add
-layout flag to pdftotext to preserve structure
Best Practices
- Always verify tools before starting - Check which generation tools are available
- Preserve layout during extraction - Use
pdftotext -layout for better structure
- Test with sample content first - Generate a test PDF before full report
- Validate output PDF - Check page count and verify content was included
- Handle special characters - Escape HTML entities when using wkhtmltopdf
- Clean up temporary files - Remove intermediate .ps, .html, .txt files after generation
- Document tool choices - Note which generation method was used for reproducibility
Quick Start Template
#!/bin/bash
set -e
SOURCE_DIR="${1:-source_pdfs}"
OUTPUT_PDF="${2:-final_report.pdf}"
WORKDIR="workdir_$$"
mkdir -p "$WORKDIR/extracted"
trap "rm -rf $WORKDIR" EXIT
for tool in pdfinfo pdftotext; do
if ! which "$tool" &>/dev/null; then
echo "ERROR: $tool not found. Install poppler-utils."
exit 1
fi
done
echo "Extracting PDFs from $SOURCE_DIR..."
for pdf in "$SOURCE_DIR"/*.pdf; do
[ -f "$pdf" ] || continue
name=$(basename "$pdf" .pdf)
pdftotext -layout "$pdf" "$WORKDIR/extracted/${name}.txt"
echo " Extracted: "
{
txt /*.txt;
[ -f ] ||
name=$( .txt)
} >
enscript &>/dev/null && ps2pdf &>/dev/null;
enscript -B -o - | ps2pdf -
pandoc &>/dev/null;
pandoc -o
1
pages=$(pdfinfo | grep Pages | awk )