TeX Alchemist Online

TeX のこと,フォントのこと,Mac のこと

macOS 12.3 以降の環境でコマンドラインからPDFを結合する

前記事の続編です。

doratex.hatenablog.jp

かつては Automator アクションに内蔵されたスクリプトが便利だった

macOS 12.2 以前では,システム標準にインストールされているAutomatorアクションの中に内包された Python スクリプトを呼び出すことで,コマンドラインから複数のPDFを結合することが可能でした。

例えば,input1.pdfinput3.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 を代替するという目的は達成できたことでありましょう。