Here is the Swift version that can be run as a Swift script or a compiled Swift command-line application. It assumes that the first PDF file on the command line is your non-existent arbitrarily named output PDF file that the remaining PDFs on the command-line will be merged too. PDF tilde paths are accepted. There are instructions in the comments on how to build a universal2 application.
You will need the Swift interpreter/compiler for this script to work. If you have installed Xcode 13.2.1, or later, that is fine, but you can also save about 40GB of storage by just installing the Command Line tools for your version of Xcode. I have tested this script and compiled application on the following:
- macOS 11.6.8
- Xcode 13.2.1
- Command Line Tools for Xcode 13.2 (3.4 GB installed)
- Swift v5.5.2
- macOS 12.5
- Xcode 13.4.1
- Command Line Tools for Xcode 13.4 (4.0 GB installed)
- Swift v5.6.1
This is the simplest means to get the Command Line tools:
xcode-select --install
if this tells you they are already installed, it won't tell you what version, so to be current for your given operating system, sign into developer.apple.com/downloads/other with your Apple ID, and choose the appropriate from above.
Here is the Swift code to merge PDFs into a specified output PDF. It is a year old, but still compiles and runs correctly per the above Swift versions and platforms:
#!/usr/bin/swift
/*
pdfmerge.swift - merge pdf files using Apple's PDFKit framework
Note: final merged PDF is smaller than sum of all input PDF, and all
original PDF annotations are preserved.
Compilation:
swiftc -Osize -o pdfm pdfmerge.swift -framework Foundation -framework PDFKit
or create a universal2 binary on M1 Macs:
swiftc -Osize -o pdfm_x86_64 pdfmerge.swift -framework Foundation -framework PDFKit -target x86_64-apple-macos10.9
swiftc -Osize -o pdfm_arm64 pdfmerge.swift -framework Foundation -framework PDFKit
lipo -create -output pdfm pdfm_arm64 pdfm_x86_64
lipo -archs pdfm
Usage: pdfm merged.pdf file1.pdf file2.pdf... filen.pdf
Reference: https://stackoverflow.com/questions/48820512/how-to-combine-two-pdfs-without-losing-any-information
Tested: macOS 11.4, macOS 10.14.6 (18G9216), Swiftc v5.4
Revisions: added file and error checking as original code example had neither
VikingOSX, 2021-06-21, Apple Support Communities, all attribution to original stackoverflow author.
*/
import Foundation
import PDFKit
let fileManager = FileManager.default
let args = CommandLine.arguments.map { URL(fileURLWithPath: $0) }
// verify input files have pdf extension and exist
for i in 2..<args.count {
guard args[i].pathExtension == "pdf",
fileManager.fileExists(atPath: args[i].path) == true
else {
print("\(args[i].lastPathComponent) is either not a PDF document or it does not exist.")
exit(EXIT_FAILURE)
}
}
// start with the first real pdf to begin reading pages into memory
let doc = PDFDocument(url: args[2])!
// write the pages of each PDF into the merge
for i in 3..<args.count {
let docAdd = PDFDocument(url: args[i])!
for i in 0..<docAdd.pageCount {
let page = docAdd.page(at: i)!
doc.insert(page, at: doc.pageCount)
}
}
// write all merged pages to first (non-existent) PDF document name
guard doc.write(to: args[1]) == true else {
print("\(args[1]): could not write merged PDF.")
exit(EXIT_FAILURE)
}
exit(EXIT_SUCCESS)
Usage:
pdfmerge.swift arbitrary.pdf a.pdf b.pdf c.pdf ... x.pdf
# after compiled to mergePDF
mergePDF arbitrary.pdf a.pdf b.pdf c.pdf ... x.pdf