Created
February 6, 2025 10:42
-
-
Save pleabargain/b5079e64d88a2edd39a0ee13ec2d818c to your computer and use it in GitHub Desktop.
combine multiple PDFS into one using powershell and qpdf on win11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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