Skip to content

Instantly share code, notes, and snippets.

@pleabargain
Created February 6, 2025 10:42
Show Gist options
  • Save pleabargain/b5079e64d88a2edd39a0ee13ec2d818c to your computer and use it in GitHub Desktop.
Save pleabargain/b5079e64d88a2edd39a0ee13ec2d818c to your computer and use it in GitHub Desktop.
combine multiple PDFS into one using powershell and qpdf on win11
# PDF Merger Script using QPDF
# This script allows user to select order of PDFs and combines them into a single PDF file
# Requirements: QPDF must be installed on the system
function Get-PdfPageCount {
param (
[string]$pdfPath
)
try {
$pageCount = & qpdf --show-npages $pdfPath 2>&1
if ($LASTEXITCODE -eq 0) {
return [int]$pageCount
}
return -1
} catch {
return -1
}
}
# Display script purpose
Write-Host "`nPDF Merger Script" -ForegroundColor Cyan
Write-Host "This script will combine PDF files in your specified order.`n"
Write-Host "Requirements: QPDF must be installed on your system.`n"
# Check if QPDF is installed
try {
$qpdfVersion = & qpdf --version 2>&1
if ($LASTEXITCODE -ne 0) {
throw "QPDF not found"
}
} catch {
Write-Host "Error: QPDF is not installed or not accessible. Please install QPDF first." -ForegroundColor Red
exit 1
}
# Get all PDF files in the current directory
$pdfFiles = Get-ChildItem -Filter *.pdf | Sort-Object Name
# Check if any PDF files exist
if ($pdfFiles.Count -eq 0) {
Write-Host "No PDF files found in the current directory." -ForegroundColor Red
exit 1
}
# Display available PDF files with numbers
Write-Host "Available PDF files:" -ForegroundColor Green
$pdfDict = @{}
for ($i = 1; $i -le $pdfFiles.Count; $i++) {
$pdf = $pdfFiles[$i-1]
$pageCount = Get-PdfPageCount -pdfPath $pdf.FullName
if ($pageCount -eq -1) {
Write-Host "Error: Unable to read page count for $($pdf.Name)" -ForegroundColor Red
exit 1
}
Write-Host "$i. $($pdf.Name) ($pageCount pages)"
$pdfDict[$i] = @{
File = $pdf
Pages = $pageCount
}
}
Write-Host ""
# Create ordered list based on user input
$orderedPdfs = @()
$totalPages = 0
$usedNumbers = @()
while ($orderedPdfs.Count -lt $pdfFiles.Count) {
$remaining = $pdfFiles.Count - $orderedPdfs.Count
$nextPosition = $orderedPdfs.Count + 1
Write-Host "Select PDF #$nextPosition of $($pdfFiles.Count) ($(($pdfFiles.Count - $usedNumbers.Count)) remaining)"
$selection = Read-Host "Enter number (1-2)"
# Validate input
try {
$num = [int]$selection
if ($num -lt 1 -or $num -gt $pdfFiles.Count) {
Write-Host "Invalid number. Please enter a number between 1 and $($pdfFiles.Count)" -ForegroundColor Yellow
continue
}
if ($usedNumbers -contains $num) {
Write-Host "You've already selected this PDF. Please choose a different one." -ForegroundColor Yellow
continue
}
$orderedPdfs += $pdfDict[$num].File
$totalPages += $pdfDict[$num].Pages
$usedNumbers += $num
Write-Host "Added $($pdfDict[$num].File.Name) to position $nextPosition`n" -ForegroundColor Green
} catch {
Write-Host "Invalid input. Please enter a number." -ForegroundColor Yellow
continue
}
}
# Final confirmation
Write-Host "`nSelected PDF order:" -ForegroundColor Cyan
for ($i = 0; $i -lt $orderedPdfs.Count; $i++) {
Write-Host "$($i+1). $($orderedPdfs[$i].Name)"
}
Write-Host "`nTotal pages: $totalPages"
$confirmation = Read-Host "`nDo you want to merge these PDF files in this order? (y/n)"
if ($confirmation -ne 'y') {
Write-Host "`nOperation cancelled by user." -ForegroundColor Yellow
exit 0
}
# Create output filename with timestamp
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$outputFile = "merged_${timestamp}.pdf"
try {
# Build command string directly
$command = "qpdf --empty --pages"
# Add all PDF files to the command
foreach ($pdf in $orderedPdfs) {
$command += " `"$($pdf.FullName)`" 1-z"
}
# Add output file
$command += " -- `"$outputFile`""
# Execute QPDF command
Write-Host "`nMerging PDF files..." -ForegroundColor Yellow
$output = Invoke-Expression $command 2>&1
if ($LASTEXITCODE -ne 0) {
throw "QPDF error: $output"
}
# Verify the output file
if (Test-Path $outputFile) {
$finalPageCount = Get-PdfPageCount -pdfPath $outputFile
if ($finalPageCount -eq $totalPages) {
Write-Host "`nPDF files successfully merged into: $outputFile" -ForegroundColor Green
Write-Host "Verified page count: $finalPageCount pages" -ForegroundColor Green
} else {
Write-Host "`nWarning: Page count mismatch. Expected $totalPages pages, got $finalPageCount pages" -ForegroundColor Yellow
Write-Host "The file was still created successfully as: $outputFile" -ForegroundColor Green
}
} else {
throw "Output file was not created"
}
} catch {
Write-Host "`nError occurred while merging PDF files: $($_.Exception.Message)" -ForegroundColor Red
if (Test-Path $outputFile) {
Remove-Item $outputFile -Force
Write-Host "Cleaned up incomplete output file." -ForegroundColor Yellow
}
exit 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment