Merge PDF contents thru apple script

Jeffkr. I just tested my script a second time and it worked fine. I’m new to ASObjC and probably made some rookie mistake. I’m sure Shane will provide a working script as soon as he has the time.

BTW, I made an inconsequential change to my script above and you may want to try it again. I don’t think it will make a difference, though. Also, you may want to see if the following code actually returns the PDF’s:

set sourceFolder to ((path to desktop as text) & "View PDFs:")
set targetFile to ((path to desktop as text) & "Combined.pdf")

tell application "Finder"
	set sourceFiles to (every file in folder sourceFolder whose name ends with ".pdf") as alias list
end tell

Hello.
The colon at the very end of the pathname “View PDFs:” is useless but its availability doesn’t hurt.

I wish to point an important detail: if, at least, one of the original PDFs is protected by a password, you will get no error message but the created combined PDF will be empty.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 5 janvier 2021 19:05:08

Thank you VERY much Peavine, your script works extremely well.

Jeffkr. Thanks for letting me know–I’m glad that worked.

Very thanks to all, I made a search with Google for a similar problem: merge two separate PDF files with odd pages in one file and even pages in the other. Because the resulting file has 500 pages the work that awaited me was well beyond the time available. I therefore ended up here and thanks to your indications with lots of examples, by slightly modifying Peavine’s script, I managed to do it in just a few minutes. By this I want to thank you all for allowing this thread.

use framework "Foundation"
use framework "Quartz"
use scripting additions

set sourceFolder to ((path to desktop as text) & "View PDFs:") -- I have put here 2 files odd.pdf and even.pdf
set targetFile to ((path to desktop as text) & "Combined.pdf")

tell application "Finder"
	set sourceFiles to (every file in folder sourceFolder whose name ends with ".pdf") as alias list
end tell

mergeFiles(sourceFiles, targetFile)

on mergeFiles(sourceFiles, targetFile)
	set firstFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of item 1 of sourceFiles)
	-- /Users/stefano/Desktop/View PDFs/dispari.pdf -- 257 pages
	set secondFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of item 2 of sourceFiles)
	-- /Users/stefano/Desktop/View PDFs/pari.pdf -- 256 pages
	set firstDoc to current application's PDFDocument's alloc()'s initWithURL:firstFile
	set secondDoc to current application's PDFDocument's alloc()'s initWithURL:secondFile
	set firstDocCount to firstDoc's pageCount()
	set secondDocCount to secondDoc's pageCount()
	set Counter to 0
	-- debug first of all :-)
	--display dialog "firstDocCount = " & firstDocCount & return & "secondDocCount: " & secondDocCount
	repeat with n from 1 to firstDocCount -- repeat with n from 1 to 257
		set thePDFPageFromfirstDoc to (firstDoc's pageAtIndex:(n - 1)) -- take the current page, the first index is zero
		(secondDoc's insertPage:thePDFPageFromfirstDoc atIndex:Counter) -- insert the page at the index defined by the Counter into the temporary file
		set secondDocCount to secondDocCount + 1 -- increase the page count index of the second temporary file
		set Counter to (Counter + 1) + 1 -- advance by 2 units (existing page and added page)
	end repeat
	set mergedFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of targetFile)
	(secondDoc's writeToURL:mergedFile) -- save the temporary file to Combined.pdf
end mergeFiles

1 Like

I was looking through this thread and there are references to “framework Quartz.” Is that a framework that you download and put in the user/Library folder? I’m still learning and thought of running a few of these PDF scripts as a learning exercise. Thanks.

Homer712. The script should run fine as written–the Quartz framework doesn’t need to be installed.

BTW, you may see a “use framework ‘PDFKit’” statement in scripts that manipulate PDFs and that is already installed and will also work fine (including in Stefano_Monti’s script).

Found 216 individual frameworks folders in System/Library/Frameworks. Quartz was there as well as the PDFKit. What I initially found strange, was that all 216 folders had a date of Sept. 15, 2023, 10:47 PM. Then I looked at some of the Apple applications, and they had the same date/time. Things must get updated during macOS updates I would guess.

I tested Stefano_Monti’s script and it worked great. My source PDFs were two copies of Shane’s ASObjC book (159 pages each), and the merged PDF was created in less than a second.

As part of my ongoing effort to learn the Shortcuts app, I wrote a shortcut that does he same thing, although the shortcut solution differs in that it:

  • prompts the user to select the source PDF files;
  • creates the merged PDF in the same folder as the source PDFs;
  • is slower but only marginally so; and
  • requires macOS Monterey or newer.

Merge PDFs.shortcut (22.7 KB)

1 Like

I want to merge all pdf that are open in Preview most of the pdf’s are open foo the web and are not saved on the hard drive, is there a way to do it or is it impossible because Apple won’t allow it to happen, like they don’t allow preview to open pdf links directly?

Keith. In my testing, PDFs opened in Preview from the internet have a temporary file on the local computer, and these temporary files can be merged and saved. The following worked on my Sonoma computer.

use framework "Foundation"
use framework "PDFKit"
use scripting additions

set targetFile to POSIX path of (path to desktop) & "Merged Files.pdf" -- edit as desired

tell application "Preview" -- add error correction if Preview not open or document not found
	activate
	set thePaths to path of every document
end tell

mergeFiles(thePaths, targetFile)

on mergeFiles(theFiles, targetFile)
	set outDoc to current application's PDFDocument's new()
	set outDocCount to outDoc's pageCount()
	repeat with aFile in theFiles
		set aFile to (current application's |NSURL|'s fileURLWithPath:aFile)
		set aDoc to (current application's PDFDocument's alloc()'s initWithURL:aFile)
		set aDocCount to aDoc's pageCount()
		repeat with i from 1 to aDocCount
			set aDocPage to (aDoc's pageAtIndex:(i - 1))
			(outDoc's insertPage:aDocPage atIndex:outDocCount)
			set outDocCount to outDocCount + 1
		end repeat
	end repeat
	set targetFile to (current application's |NSURL|'s fileURLWithPath:targetFile)
	set fileExists to targetFile's checkResourceIsReachableAndReturnError:(missing value)
	if (fileExists as boolean) is true then display dialog "The target file already exists" buttons {"OK"} cancel button 1 default button 1
	outDoc's writeToURL:targetFile
end mergeFiles