Apple Event: May 7th at 7 am PT

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

MacOS 12.3 (Monterey) Automator Combine PDF Pages breaks workflows

I have a few workflows that have stopped working because when the "Combine PDF Pages" action runs, it fails.


I get the error "The action “Combine PDF Pages” encountered an error: “The operation couldn’t be completed. Command line tool returned error 127.: 127”


If anyone has any ideas or how to fix this I would be very appreciative.


Thanks in advance.


Brandon

MacBook Pro 13″, macOS 12.3

Posted on Mar 22, 2022 7:09 AM

Reply
Question marked as Best reply

Posted on Mar 22, 2022 10:14 AM

As an Automator Quick Action (e.g. QA Merge PDF) where you select the PDF in the Finder in the order you want them merged, and then on the first selected PDF, you control-click (two-finger tap) to access Quick Actions > QA Merge PDF from the secondary menu. The merged PDF will be written to your Desktop as merged.pdf.



And then drag/drop the Utilities Library > Run AppleScript action below it. Select everything in that Run AppleScript window and delete it. Then copy/paste the following back into that Run AppleScript action window:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property PDFDocument : a reference to current application's PDFDocument

on run {input, parameters}
	
	# tilde path to absolute path
	set merged_pdf to (NSString's stringWithString:"~/Desktop/merged.pdf")'s stringByStandardizingPath()
	
	set outurl to NSURL's fileURLWithPath:(POSIX path of (item 1 of input))
	set outpdf to PDFDocument's alloc()'s initWithURL:outurl
	set pdfList to rest of input
	set lastPage to outpdf's pageCount()
	
	repeat with pdfdoc in pdfList
		set thisURL to (NSURL's fileURLWithPath:((POSIX path of pdfdoc) as text))
		set thisPDF to (PDFDocument's alloc()'s initWithURL:thisURL)
		
		# PDF pages are zero-based
		repeat with n from 1 to thisPDF's pageCount()
			set this_page to (thisPDF's pageAtIndex:(n - 1))
			(outpdf's insertPage:this_page atIndex:lastPage)
			set lastPage to outpdf's pageCount()
		end repeat
	end repeat
	outpdf's writeToFile:merged_pdf
	return
end run


Click the hammer icon in that Run AppleScript Action to compile this code, and then Save the Quick Action. I have used an example name for it above.

Similar questions

39 replies
Question marked as Best reply

Mar 22, 2022 10:14 AM in response to VikingOSX

As an Automator Quick Action (e.g. QA Merge PDF) where you select the PDF in the Finder in the order you want them merged, and then on the first selected PDF, you control-click (two-finger tap) to access Quick Actions > QA Merge PDF from the secondary menu. The merged PDF will be written to your Desktop as merged.pdf.



And then drag/drop the Utilities Library > Run AppleScript action below it. Select everything in that Run AppleScript window and delete it. Then copy/paste the following back into that Run AppleScript action window:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property PDFDocument : a reference to current application's PDFDocument

on run {input, parameters}
	
	# tilde path to absolute path
	set merged_pdf to (NSString's stringWithString:"~/Desktop/merged.pdf")'s stringByStandardizingPath()
	
	set outurl to NSURL's fileURLWithPath:(POSIX path of (item 1 of input))
	set outpdf to PDFDocument's alloc()'s initWithURL:outurl
	set pdfList to rest of input
	set lastPage to outpdf's pageCount()
	
	repeat with pdfdoc in pdfList
		set thisURL to (NSURL's fileURLWithPath:((POSIX path of pdfdoc) as text))
		set thisPDF to (PDFDocument's alloc()'s initWithURL:thisURL)
		
		# PDF pages are zero-based
		repeat with n from 1 to thisPDF's pageCount()
			set this_page to (thisPDF's pageAtIndex:(n - 1))
			(outpdf's insertPage:this_page atIndex:lastPage)
			set lastPage to outpdf's pageCount()
		end repeat
	end repeat
	outpdf's writeToFile:merged_pdf
	return
end run


Click the hammer icon in that Run AppleScript Action to compile this code, and then Save the Quick Action. I have used an example name for it above.

Mar 22, 2022 8:08 AM in response to 3point3

For years, the combined PDF action in Automator used a command-line Python script within the action, and now that Apple has removed Python from Monterey 12.3, it has broken that action's internal Python script. Apple apparently forgot about their production code that was impacted by this Python removal. The only fix for this would have to come from Apple in a future Monterey update.





Mar 22, 2022 9:04 AM in response to VikingOSX

The following AppleScript will allow you to select n-tuple PDFs from a file chooser, and then merge them in selection order to a user-designated output pdf (in this case ~/Desktop/merged.pdf). With little effort, this AppleScript can be adopted for use in a Run AppleScript action in an Automator Application, Quick Action, or Shortcut.


Copy and paste into Apple's Script Editor, compile, and run to test. Does not change any existing PDF.


(*
  merge_pdf.applescript
  
  Prompt user for PDF filenames to merge using the ⌘-key for multiple selection.
  PDF will be merged in the order of their selection and written to an arbitrary
  PDF filename on the Desktop (in this example, merged.pdf)
  
  Tested: macOS 11.4, 11.6.5, 12.3
  VikingOSX, 2021-06-24, Apple Support Communities, No warranty/support implied.
*)

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property PDFDocument : a reference to current application's PDFDocument

# tilde path to absolute path
set merged_pdf to (NSString's stringWithString:"~/Desktop/merged.pdf")'s stringByStandardizingPath()

set msg to "Select multiple PDF using the ⌘-key in the order of your merge preference."
set pdfList to (choose file with prompt msg of type {"com.adobe.pdf"} default location (path to desktop) with multiple selections allowed)

set outurl to NSURL's fileURLWithPath:(POSIX path of (item 1 of pdfList))
set outpdf to PDFDocument's alloc()'s initWithURL:outurl
set pdfList to rest of pdfList
set lastPage to outpdf's pageCount()

repeat with pdfdoc in pdfList
	set thisURL to (NSURL's fileURLWithPath:((POSIX path of pdfdoc) as text))
	set thisPDF to (PDFDocument's alloc()'s initWithURL:thisURL)
	
	# PDF pages are zero-based
	repeat with n from 1 to thisPDF's pageCount()
		set this_page to (thisPDF's pageAtIndex:(n - 1))
		(outpdf's insertPage:this_page atIndex:lastPage)
		set lastPage to outpdf's pageCount()
	end repeat
end repeat
outpdf's writeToFile:merged_pdf
return


I also have this written in Swift for those that want a compiled tool.

Aug 12, 2022 4:08 PM in response to cbscd

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:


  1. macOS 11.6.8
    1. Xcode 13.2.1
    2. Command Line Tools for Xcode 13.2 (3.4 GB installed)
    3. Swift v5.5.2
  2. macOS 12.5
    1. Xcode 13.4.1
    2. Command Line Tools for Xcode 13.4 (4.0 GB installed)
    3. 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


Apr 1, 2022 11:55 AM in response to Steve_IR

There is nothing to pass to a subsequent action in the existing script, so one must first write that content to disk, and then use a Get Specified Finder Items action with a merged.pdf entry, and then follow it with that Move Finder Items action set to the preferred folder location.


The following is tested to merge several selected PDFs into the output file merged.pdf. Once it is written to disk, then you can tell the Finder to get that file and move it. The Run AppleScript action content has not changed, though I have added the following two actions to it. The end result is that the merged.pdf file is moved into a Desktop/PDFs folder.






Apr 18, 2022 3:36 AM in response to Steve_IR

Hi,


I combined VikingOSX's script with some dialog boxes into a automator workflow. Unzip that and place it in ~/Library/Services, You can customize the workflow if you like.


The workflow combines two of more PDFs ***** in the same order, as they had been selected in Finder*****.

In the last dialog you can change the name of the new combined PDF, if you want.


If you want to rearrange pages in that new PDF, you can do that in Preview.


best, Marcus



[Dropbox Link removed by Apple, what makes the message worthless without a file]

so I give it a try with an iCloud Share, hmpf …

https://www.icloud.com/iclouddrive/085VkneYpZcE6OpLHarOh1GJg#Join-PDFs_on_Desktop-EN


Apr 18, 2022 5:47 AM in response to MattiasRasmusson

No. There is no plan to entirely replicate the Python script functionality underlying that Automator action.


I am looking at the original join.py in that Automator action and it leans heavily on Quartz CoreGraphics which may in turn, make it problematic for implementing this shuffle functionality in AppleScript/Objective-C. No promises.

Apr 19, 2022 7:33 AM in response to 3point3

I need to use the quartz filter in Automator to reduce PDF file size so I couldn't make the switch to Shortcuts for the make PDF action.


However I was able to run quartz filter in Automator and then have Automator run the script to start a Shortcuts workflow that merges PDFs using the following AppleScript.


tell application "Shortcuts Events"
	run shortcut "Name of Workflow in Shortcuts"
end tell


I hope that this is helpful to someone out there.

Apr 19, 2022 9:28 AM in response to VikingOSX

Ok. I sat down with Apple's join.py and looked at the code involved with the shuffle feature. Neither AppleScript/Objective-C nor JavaScript for Automation are being cooperative in the shuffle functionality migration and I have given up as it is consuming too much time. It might be possible in Objective-C or Swift, but that limits the user adaptation here.

Apr 22, 2022 4:30 AM in response to VikingOSX

Hello,


I used VikingOSX’s script to automate the combining of all pdf's in a folder into a single file. It works perfectly.


How would you replace the "choose file" in the line below with the hardcoded path? Folder is "Macintosh HD/myusername/Dropbox/…".


set pdfList to (choose file with prompt msg of type {"com.adobe.pdf"} default location (path to desktop) with multiple selections allowed)


Please note that the list must remain sorted.


Thank you.

Apr 22, 2022 5:39 AM in response to Duciel

I provided an example Quick Action which gets its PDF documents from Finder selection order, and where one would determine their own folder location for that selection process. In that case, the entire choose file clause is omitted.


If you want the choose file clause, but rather a change to the default selection location, that can be done in this manner, and provides the full AppleScript HFS path to your Dropbox folder. That trailing colon is equivaent to the POSIX '/'.


use scripting additions

set dropbox to ((path to home folder as text) & "Dropbox:") as alias
set pdfList to (choose file of type "PDF" default location dropbox with multiple selections allowed)



Apr 22, 2022 6:16 AM in response to VikingOSX

Thank you very much for your quick response.


What I would like is indeed to omit the choose file clause. (Since the path is known in my case, it is not necessary for me to select it every time I run the script).


But, as I have never written Applescript before, I don't know how to assign pdfList its hardcoded value. Besides, the list must be sorted alphabetically.


Please excuse my English which is not my native language.


Thank you.

MacOS 12.3 (Monterey) Automator Combine PDF Pages breaks workflows

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.