Seiten in PDF zählen (für Nicht-Techniker, Mac-Benutzer)

Ich habe eine Person, die Seiten von vielleicht 2-3000 PDFs zählen möchte. Sie benötigt eine Gesamtzahl aller PDFs zusammen (es wird wahrscheinlich ungefähr 20.000 betragen, verteilt auf die 3.000 PDFs) - es sind keine weiteren Details erforderlich.

Ich habe über Adobe Combine nachgedacht und dann eine Seitenzahl erhalten, aber nur mit ~ 500 Dateien getestet, es geht ziemlich langsam!

Erwähnenswert ist, dass Sie früher mehrere PDFs gleichzeitig in der Vorschau öffnen und eine Seitenzahl erhalten konnten! Früher hat es ziemlich gut funktioniert, sogar über 2-300 Dateien hinweg!

Danke für deine Gedanken.

Möchte sie die Seitenzahl für jedes PDF oder nur die Gesamtseitenzahl wissen? Befinden sich die PDFs in einem Ordner oder in vielen Ordnern in einer Baumstruktur?
Gesamtseitenzahl. nicht für jeden. Die Dateien befinden sich in mehreren Ordnern, aber ich kann sie problemlos verschieben lassen.
Es wäre gut zu wissen, ob eine dieser Lösungen schneller ist als Ihre Zusammenführungsmethode. Die Zusammenführungsmethode ist ziemlich einfach und unkompliziert. Nur ein Gedanke.
@jmh Joshs Skript war viel, viel schneller als Merge in meinem Anwendungsfall (Hunderte von Dateien mit jeweils Hunderten von Seiten). Wahrscheinlich würde eine Zusammenführung Stunden oder sogar Tage dauern, und Sie erhalten am Ende ein Duplikat Ihrer Dateien (in diesem Fall viel Speicherplatz auf dem Laufwerk). Joshs Skript dauerte Minuten (vielleicht 15 in der Verarbeitung).

Antworten (2)

Einfach.

Erstellen Sie ein Apple-Skript, exportieren Sie es als Anwendung und senden Sie ihr dann die Anwendung.

AppleScript-Code:

set totalPages to 0
set numDocs to 1
set myFiles to choose file with prompt "Select all PDF's" with multiple selections allowed
set nummyFiles to length of myFiles
set progress total steps to nummyFiles
set progress completed steps to 0
set progress description to "Processing PDF's..."
set progress additional description to "Preparing to process."
repeat with i in myFiles
    set progress additional description to "Processing PDF " & numDocs & " of " & nummyFiles
    set progress completed steps to numDocs
    set myfile to POSIX path of i
    set pageCount to (do shell script "/usr/bin/mdls " & quoted form of myfile & " | /usr/bin/awk '/kMDItemNumberOfPages/{print $3}'") as integer
    set totalPages to (totalPages + pageCount)
    set numDocs to (numDocs + 1)
end repeat
display dialog "There are " & totalPages & " pages in this PDF"
  1. Offen/Applications/Utilities/Script Editor.app
  2. Datei > Neu
  3. Kopieren Sie den obigen Code und fügen Sie ihn ein
  4. Datei > Exportieren
  5. Dateiformat: Anwendung
  6. Exportierte Anwendung senden
Ich habe mich gefragt, ob myFileses mit mehreren hundert ausgewählten Dateien brechen könnte. 3.0000 sind eine Menge Dateien. Warum den Benutzer nicht dazu bringen, einen Ordner auszuwählen und dann die Schleife im Shell-Skript auszuführen?
Das ist eine Möglichkeit, obwohl ich das noch nie erlebt habe. Können Sie bitte erklären, was Sie meinen? Ich verstehe nicht, was Ihre Frage bedeutet.
Ich werde jetzt mit 3.000 Dateien testen.
@TonyWilliams Gerade mit 3.000 Dateien getestet, es hat super funktioniert! Jeder hatte 3 Seiten mit insgesamt 9.000. Ich habe sogar einen Fortschrittsbalken hinzugefügt.
Das ist fantastisch. Das könntest du aufpolieren und im App Store verkaufen. lol. Frage: Muss die Indizierung für die Dateien abgeschlossen sein? Da die Seitenzahl zurückkehrt, bin ich von ihr anscheinend ... niedrig.
Froh, dass ich helfen konnte! Leider ist dies eine Einschränkung von Apple Script. Ich weiß/glaube nicht, dass es eine Möglichkeit gibt, ein Dialogfeld zum Laden zu haben, während alle Dateien in die Liste eingetragen werden. Ich werde aber sehen, was ich tun kann....
@Gryph Lol das ist nicht nötig. Aber da es für einen guten Zweck ist ... spenden Sie an jede Organisation, die Sie für richtig halten. Ich bin sicher, sie werden es zu schätzen wissen.

Ich habe Joshs Ansatz ausprobiert mdlsund eine überraschende Anzahl von (Nullen) für kMDItemNumberOfPages gefunden.

Also habe ich den Kurs gewechselt und AppleScriptObjC verwendet, um die Seiten in den gefundenen PDF-Dateien direkt zu zählen.

Das Skript wird direkt von der Skript-Editor.app oder von einem Skript-Applet ausgeführt.

Es wird ein Bericht in TextEdit erstellt, der wie folgt aussieht:

--------------------------
PDF files found  :  460
Total Pages      :  27052
Total Errors     :  0
--------------------------

Dieser Lauf dauerte auf meinem 17-Zoll-i7-MacBook Pro von Mitte 2010 genau 10 Sekunden.

Die folgende Zeile muss im Skript geändert werden, um das Zielverzeichnis auf dem System des Benutzers korrekt widerzuspiegeln:

property searchPath : "~/Downloads"

(Obwohl ich es gerne auf Anfrage für das vordere Fenster im Finder zum Laufen bringen würde.)

Das Skript ist derzeit im Zielverzeichnis rekursiv eingestellt.

-------------------------------------------------------------------------------------------
# Auth: Christopher Stone { With many thanks to Shane Stanley and Nigel Garvey }
# dCre: 2018/04/27 01:30
# dMod: 2018/04/27 02:50
# Appl: AppleScriptObjC, TextEdit
# Task: Find all PDF files in a directory tree – count and report all pages.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @TextEdit, @Find, @PDF, @Files, @Directory, @Tree, @Recursive, @Count, @Report, @Pages, @Progress_Bar, @Bar
# Vers: 1.00
-------------------------------------------------------------------------------------------
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "Quartz" -- for PDF features
use scripting additions
-------------------------------------------------------------------------------------------
property searchPath : "~/Downloads"
property searchRecursively : true
-------------------------------------------------------------------------------------------

set pageCountList to {}
set searchPath to ((current application's NSString's stringWithString:searchPath)'s stringByExpandingTildeInPath) as text
set foundItemList to my filteredContents:searchPath withUTI:{"com.adobe.pdf"} |returning|:"path" recursive:searchRecursively

set totalStepNum to length of foundItemList
set progress total steps to totalStepNum
set progress completed steps to 0
set progress description to "Processing PDF's..."
set progress additional description to "Preparing to process."
set numberOfProcessedDocuments to 0

repeat with pdfFilePath in foundItemList
    set numberOfProcessedDocuments to (numberOfProcessedDocuments + 1)
    set progress additional description to "Processing PDF " & numberOfProcessedDocuments & " of " & totalStepNum
    set progress completed steps to numberOfProcessedDocuments
    try
        set anNSURL to (current application's |NSURL|'s fileURLWithPath:(contents of pdfFilePath))
        set theDoc to (current application's PDFDocument's alloc()'s initWithURL:anNSURL)
        set end of pageCountList to theDoc's pageCount() as integer
    on error
        set end of pageCountList to "Error --> " & name of (info for (contents of pdfFilePath))
    end try
end repeat

set errorList to text of pageCountList
set filesFoundCount to length of foundItemList
set pageCountList to integers of pageCountList
set pageCount to its sumList(pageCountList)

set pdfPageReport to "
--------------------------
PDF files found  :  " & filesFoundCount & "
Total Pages      :  " & pageCount & "
Total Errors     :  " & length of errorList & "
--------------------------
"

tell application "TextEdit"
    launch -- prevent the Open dialog from opening.
    activate
    set newDoc to make new document with properties {text:pdfPageReport}
    tell newDoc
        set font to "Menlo"
        set size to "14"
    end tell
end tell

-------------------------------------------------------------------------------------------
--» HANDLERS
-------------------------------------------------------------------------------------------
on filteredContents:folderPath withUTI:wUTI |returning|:returnType recursive:wRecursive
    set theFolderURL to current application's |NSURL|'s fileURLWithPath:folderPath
    set typeIdentifierKey to current application's NSURLTypeIdentifierKey
    set keysToRequest to current application's NSArray's arrayWithObject:(typeIdentifierKey)
    set theFileManager to current application's NSFileManager's defaultManager()

    # Get all items in folder descending into subfolders if asked.
    if wRecursive = true then
        set allURLs to (theFileManager's enumeratorAtURL:theFolderURL includingPropertiesForKeys:keysToRequest options:6 errorHandler:(missing value))'s allObjects()
    else
        set allURLs to theFileManager's contentsOfDirectoryAtURL:theFolderURL includingPropertiesForKeys:keysToRequest options:4 |error|:(missing value)
    end if

    # Build an or predicate to test each URL's UTI against all the specified ones.
    set predArray to current application's NSMutableArray's new()
    repeat with aKind in wUTI
        (predArray's addObject:(current application's NSPredicate's predicateWithFormat_("self UTI-CONFORMS-TO %@", aKind)))
    end repeat
    set thePredicate to current application's NSCompoundPredicate's orPredicateWithSubpredicates:predArray

    # Build a list of those URLs whose UTIs satisfy the predicate …
    script o
        property theURLs : {}
    end script
    # … keeping AS texts listing the UTIs tried so that they don't need to be tested again.

    set conformingUTIs to ""
    set unconformingUTIs to ""

    repeat with oneURL in allURLs
        set thisUTI to end of (oneURL's getResourceValue:(reference) forKey:typeIdentifierKey |error|:(missing value))
        # It's only necessary to test this UTI for conformity if it hasn't come up before.
        set thisUTIAsText to linefeed & thisUTI & linefeed
        if (unconformingUTIs contains thisUTIAsText) then
            # Do nothing.
        else if (conformingUTIs contains thisUTIAsText) then
            # Add this URL to the output list.
            set end of o's theURLs to oneURL
        else if ((thePredicate's evaluateWithObject:thisUTI) as boolean) then -- This works even if thisUTI is missing value.
            # Add this URL to the output list and append the UTI to the conforming-UTI text.
            set end of o's theURLs to oneURL
            set conformingUTIs to conformingUTIs & thisUTIAsText
        else
            # Append this UTI to the unconforming-UTI text.
            set unconformingUTIs to unconformingUTIs & thisUTIAsText
        end if
    end repeat

    # Get an array version of the URL list and use this to derive the final output.
    set theURLs to current application's NSArray's arrayWithArray:(o's theURLs)
    if returnType = "name" then return (theURLs's valueForKey:"lastPathComponent") as list
    if returnType = "path" then return (theURLs's valueForKey:"path") as list
    if returnType = "url" then return theURLs
    return theURLs as list

end filteredContents:withUTI:|returning|:recursive:
-------------------------------------------------------------------------------------------
on sumList(theList)
    set theNSArray to current application's NSArray's arrayWithArray:theList
    set theSum to (theNSArray's valueForKeyPath:"@sum.self") as integer
    return theSum
end sumList
-------------------------------------------------------------------------------------------

Da dieses Tier nur leicht getestet wurde, gebe ich keine Garantien, aber ich bin bisher damit zufrieden.

-ccs

Interessant - ich habe keine Nullen bekommen. Ich habe verschiedene Merge-Kombinationen im Vergleich zu einer Handzählung im Vergleich zu Joshs Ansatz getestet und sie kamen alle gleich heraus. Diese Methode ist aber schneller, das kann ich bestätigen. Es wäre schön, wenn man zwei "richtige" Antworten geben könnte.
Nur ein Followup - dieses Skript ist viel schneller als das obige Skript. Es ist auch ganz nett, die Anzahl der gezählten PDFs und mögliche Fehler enthalten zu haben (habe keine über mehrere Tests von Hunderten von Dateien gehabt).
Ich würde gerne daran arbeiten, unsere Skripte zu kombinieren. Verwenden Sie Ihre Methode zum Zählen, aber meine zum Auswählen des Verzeichnisses, und fügen Sie auch die Möglichkeit hinzu, bestimmte Dokumente auszuwählen. Erstellen Sie außerdem eine andere Methode, um Ergebnisse anzuzeigen.
Das Beste aus beiden Welten, ja, ich stimme zu - sie haben jeweils unterschiedliche Anwendungsfälle, wie Sie oben anmerken. Ich kann beides ohne Probleme verwenden, aber Ihres ist für Nicht-Lesekundige einfacher. Christophers ist jedoch viel, viel schneller. Wirklich interessant, die Unterschiede zu sehen. Ich habe diese Frage sehr gemocht.