Wie kann ich alle Seiten in einem PDF mit nativen macOS-Tools programmgesteuert drehen?

Bei einem gegebenen Dateipfad muss ich alle Seiten in einem PDF an diesem Dateipfad drehen, wobei nichts verwendet wird, was nicht in macOS enthalten ist. Der Wrapper dafür wird AppleScript sein, daher habe ich auch Zugriff auf die Befehlszeile und damit auf alle standardmäßig mit macOS installierten Skriptsprachen, aber nichts, was erforderlich wäre, brewoder beispielsweise Pythons pip.

Dieser Beitrag bei SuperUser kann Ihnen vielleicht weiterhelfen.
@icondaemon erfordert dies nicht zusätzliche Software?
Kann ich vorschlagen, dass Sie Ihre Frage so bearbeiten , dass sie enthält, welche Version von macOS Sie ausführen? Können Sie auch erläutern, wie Sie die Seiten drehen müssen (z. B. 90 ° im Uhrzeigersinn oder ...)? Wäre schließlich eine Lösung mit Automator akzeptabel oder eine mit JavaScript for Automation (JXA)?
@Patrix - stimmt. Ich habe letztes Jahr ein paar Tage damit verbracht, native PDF-Manipulationstools zu finden, die über die Befehlszeile verfügbar sind, und habe nur 16 Automatisierungen in /System/Library/Automator gefunden, aber keine, die das tun, was das OP benötigt, wie er wahrscheinlich selbst herausgefunden hat. Automator hat eine Funktion zum Drehen von Bildern für die Vorschau, aber ich glaube nicht, dass das bei PDF-Dateien funktioniert.
Ich untersuche Automators Split PDF, Rotate Images(oder ein AppleScript, das ich habe, das mit einseitigen PDFs funktioniert) und Combine PDF Pages. Diese könnten die Arbeit erledigen.

Antworten (2)

Meines Wissens hat macOS keine native ausführbare Befehlszeilen-Unix-Datei , die alle Seiten in einem PDF drehen kann (während die textbasierten textbasiert bleiben). kann ein einseitiges PDF drehen, das resultierende PDF ist jedoch ein gekapseltes Bild , kein Text , wenn es sich zunächst um eine Textbasis handelte. Ich bin mir auch nicht sicher, ob es einen Weg mit einfachem AppleScript gibt , anders als über UI Scripting der Standardvorschauanwendung , ohne zu AppleScriptObjC ( Cocoa-AppleScript ) zu gehen und odersip Python usw.

Die Verwendung von Befehlszeilendienstprogrammen von Drittanbietern ist wahrscheinlich am einfachsten, aber Sie sagten, dass dies nur mit einem Standardteil von macOS erfolgen muss . Daher biete ich eine AppleScript- Lösung an, die UI Scripting verwendet , die standardmäßige Vorschauanwendung , die verwendet werden kann, falls es mit AppleScriptObjC oder ohne Dienstprogramme von Drittanbietern usw. keine andere Möglichkeit gibt.

Diese angebotene (und codierte) Lösung geht davon aus, dass die Vorschau die Standardanwendung für PDF- Dokumente ist , und verwendet sie, um alle Seiten im PDF- Dokument zu drehen . Es ist auch als Automator- Workflow eingerichtet . (Obwohl es andere Möglichkeiten gibt, den unten gezeigten AppleScript- Code einzubinden .)

Erstellen Sie zunächst im Finder eine Kopie der Ziel- PDF- Dokumente und arbeiten Sie mit diesen.

Erstellen Sie in Automator ein neues Workflow- Dokument und fügen Sie die folgenden Aktionen hinzu :

  • Holen Sie sich bestimmte Finder-Objekte
    • Fügen Sie dieser Aktion das kopierte Ziel - PDF - Dokument hinzu .
  • Führen Sie das AppleScript-Skript aus
    • Ersetzen Sie den Standardcode durch den folgenden Code :

AppleScript -Code :

on run {input}
    set thisLong to 0.25 -- # The value of 'thisLong' is decimal seconds delay between keystrokes, adjust as necessary.
    set theRotation to "r" -- # Valid values are 'l' or 'r' for Rotate Left or Rotate Right.
    set theViewMenuCheckedList to {}
    set theMenuItemChecked to missing value
    repeat with thisItem in input
        tell application "Finder" to open file thisItem -- # By default, in this use case, the PDF file will open in Preview.
        delay 1 --  # Adjust as necessary. This is the only 'delay' not defined by the value of 'thisLong'.
        tell application "System Events"
            perform action "AXRaise" of window 1 of application process "Preview" -- # Just to make sure 'window 1' is front-most.
            delay thisLong
            --  # Ascertain which of the first six 'View' menu items is checked.
            set theViewMenuCheckedList to (value of attribute "AXMenuItemMarkChar" of menu items 1 thru 6 of menu 1 of menu bar item 5 of menu bar 1 of application process "Preview")
            repeat with i from 1 to 6
                if item i in theViewMenuCheckedList is not missing value then
                    set theMenuItemChecked to i as integer
                    exit repeat
                end if
            end repeat
            --  # Process keystrokes based on which 'View' menu item is checked.
            --  # This is being done so the subsequent keystroke ⌘A 'Select All' 
            --  # occurs on the 'Thumbnails', not the body of the document.
            if theMenuItemChecked is not 2 then
                repeat with thisKey in {"2", "1", "2"}
                    keystroke thisKey using {option down, command down}
                    delay thisLong
                end repeat
            else
                repeat with thisKey in {"1", "2"}
                    keystroke thisKey using {option down, command down}
                    delay thisLong
                end repeat
            end if
            repeat with thisKey in {"a", theRotation as text, "s"} -- # {Select All, Rotate Direction, Save}
                keystroke thisKey using {command down}
                delay thisLong
            end repeat
            keystroke theMenuItemChecked as text using {option down, command down} -- # Resets the 'View' menu to the original view.
            delay thisLong
            keystroke "w" using {command down} -- # Close Window.
        end tell
    end repeat
end run

Anmerkungen:

  • Da dieses Skript UI-Skripting verwendet , muss die laufende App bei Ausführung über Automator (oder Skript-Editor ) zu Systemeinstellungen > Sicherheit & Datenschutz > Eingabehilfen hinzugefügt werden , damit sie ordnungsgemäß ausgeführt werden kann . Als Anwendung gespeichert , muss die gespeicherte Anwendung hinzugefügt werden.
  • Auch bei der UI-Skripterstellung muss der Wert der delay Befehle möglicherweise für die Verwendung auf Ihrem System geändert werden (und/oder gegebenenfalls zusätzliche delay Befehle hinzugefügt werden, obwohl in diesem Fall keine zusätzlichen delay Befehle erforderlich sein sollten). Es sollte selbstverständlich sein, dies jedoch zuerst an einer Reihe von Dokumenten zu testen, um sicherzustellen, dass der Wert für thisLongauf Ihrem System funktioniert. Auf meinem System funktionierte dies wie codiert.
  • Wenn Sie UI-Scripting auf diese Weise verwenden, müssen Sie das System nach dem Start der Aufgabe in Ruhe lassen und die Verarbeitung der Dateien beenden. Der Versuch, Multitasking zu betreiben, wird den Fokus nur von der anstehenden Aufgabe weglenken und dazu führen, dass sie fehlschlägt.
  • Wenn Sie mehr als einmal drehen müssen, fügen Sie zusätzlich theRotation as text,hinzu:

      repeat with thisKey in {"a", theRotation as text, "s"} -- # {Select All, Rotate Direction, Save}
    

    Beispiel:

      repeat with thisKey in {"a", theRotation as text, theRotation as text, "s"}
    

Dieses Python-Skript dreht alle Seiten von PDFs, die als Argumente angegeben werden, um 90º im Uhrzeigersinn und speichert das Ergebnis in einer neuen Datei mit angehängtem "+90" an den Dateinamen.

#!/usr/bin/python
# coding=utf-8
# Produces new PDF file with all pages rotated by 90 degrees.

import sys
import os
from Quartz import PDFDocument
from CoreFoundation import NSURL

if __name__ == '__main__':

    for filename in sys.argv[1:]:
        filename = filename.decode('utf-8')
        shortName = os.path.splitext(filename)[0]
        outFilename = shortName + "+90.pdf"
        pdfURL = NSURL.fileURLWithPath_(filename)
        pdfDoc = PDFDocument.alloc().initWithURL_(pdfURL)
        if pdfDoc:
            pages = pdfDoc.pageCount()
            for p in range(0, pages):
                page = pdfDoc.pageAtIndex_(p)
                existingRotation = page.rotation()
                newRotation = existingRotation + 90
                page.setRotation_(newRotation)

            pdfDoc.writeToFile_(outFilename)