前記事の続編です。
かつては Automator アクションに内蔵されたスクリプトが便利だった
macOS 12.2 以前では,システム標準にインストールされているAutomatorアクションの中に内包された Python スクリプトを呼び出すことで,コマンドラインから複数のPDFを結合することが可能でした。
例えば,input1.pdf
~input3.pdf
を結合して output.pdf
を得たい場合,次のコマンドで実行できました。
$ /System/Library/Automator/"Combine PDF Pages".action/Contents/Resources/join.py -o output.pdf input1.pdf input2.pdf input3.pdf
この join.py
というスクリプトは,Python2 + PyObjC で書かれたスクリプトで,内部的には macOS の API を PyObjC ブリッジで呼び出すことでPDFを結合しようというスクリプトでした。
しかし,macOS 12.3 では,Python2, Python3, PyObjC は全てまとめて macOS 標準インストールから削除されてしまいました。その結果,現時点では,この join.py
(およびこれを包含する Combine PDF Pages
という Automator アクション)は,「macOS に標準インストールされているのに動かない」という,ちぐはぐな状態となってしまっています。
そこで,この join.py
に代わり,AppleScriptObjCで「macOS標準インストール状態でコマンドラインから実行可能なPDF結合コマンド」を実現することを目指しましょう。
AppleScriptObjC でPDF結合する
まずは,AppleScriptObjC でPDF結合するスクリプトを書いてみます。
use framework "Quartz" global CA, NSURL, PDFDocument set CA to current application set NSURL to CA's NSURL set PDFDocument to CA's PDFDocument --- 与えられたPDFのページ数を返すハンドラ on pdfPageCount(pdfPath) set url to NSURL's fileURLWithPath:pdfPath set doc to PDFDocument's alloc's initWithURL:url doc's pageCount() end pdfPageCount --- PDF結合を実行するハンドラ on joinPDF(pdfPaths, outputPath) set newPDF to PDFDocument's alloc's init set pageCount to 0 repeat with pdfPath in pdfPaths set url to (NSURL's fileURLWithPath:pdfPath) set doc to (PDFDocument's alloc's initWithURL:url) set lastIndex to ((my pdfPageCount(pdfPath)) - 1) repeat with i from 0 to lastIndex (newPDF's insertPage:(doc's pageAtIndex:i) atIndex:pageCount) set pageCount to (pageCount + 1) end repeat end repeat newPDF's writeToFile:outputPath end joinPDF --- テスト実行 set sources to {"/tmp/input1.pdf", "/tmp/input2.pdf", "/tmp/input3.pdf"} set outputPath to "/tmp/output.pdf" my joinPDF(sources, outputPath)
Bashシェルスクリプトに変換する
これを次のようなシェルスクリプトとしてくるんで,join.sh
として保存します。
こうして完成した上記スクリプトは,次のように macOS 標準インストール状態でPDF結合を実現できます。
$ ./join.sh -o output.pdf input1.pdf input2.pdf input3.pdf
(スクリプト中でエラー処理は全然していませんが)とりあえずこれで join.py
を代替するという目的は達成できたことでありましょう。