7 votes

Compter les pages en PDF (pour les personnes non techniques, utilisant un Mac)

J'ai une personne qui cherche à compter les pages d'environ 2 à 3 000 PDF. Elle a besoin d'un comptage total de tous les PDF combinés (il s'agira probablement de quelque chose comme 20 000 pages réparties sur les 3 000 PDF) - aucun autre détail n'est nécessaire.

J'ai envisagé de combiner adobe et d'obtenir ensuite un nombre de pages, mais juste en testant sur ~500 fichiers, c'est assez lent !

Il est intéressant de noter qu'auparavant, il était possible d'ouvrir plusieurs pdfs simultanément dans l'aperçu et d'obtenir le nombre de pages ! Cela fonctionnait assez bien, même avec 2 à 300 fichiers !

Merci pour vos réflexions.

2 votes

Est-ce qu'elle veut savoir le nombre de pages pour chaque PDF ou seulement un nombre total de pages ? Les PDF sont-ils dans un seul dossier ou dans plusieurs dossiers dans une arborescence ?

1 votes

Le nombre total de pages, pas pour chacune. Les fichiers sont répartis dans plusieurs dossiers, mais je peux lui demander de les déplacer sans problème.

0 votes

Il serait bon de savoir si l'une ou l'autre de ces solutions est plus rapide que votre méthode de fusion. La méthode de fusion est assez simple et directe. Juste une idée.

6voto

Pirooz Points 486

Simple.

Créez un script d'Apple et exportez-le comme une application, puis envoyez-lui l'application.

Code AppleScript :

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. Ouvrir /Applications/Utilities/Script Editor.app
  2. Fichier>Nouveau
  3. Copier et coller le code ci-dessus
  4. Fichier>Exportation
  5. Format de fichier : Application
  6. Envoyer l'application exportée

1 votes

Je me demandais si myFiles pourrait se briser avec plusieurs centaines de fichiers sélectionnés. 3 0000 est un grand nombre de fichiers. Pourquoi ne pas demander à l'utilisateur de sélectionner un dossier, puis d'exécuter la boucle dans le shell script ?

1 votes

C'est une possibilité, bien que je n'aie jamais vu cela se produire. Pouvez-vous expliquer ce que vous voulez dire ? Je ne comprends pas le sens de votre question.

1 votes

Je vais maintenant faire un test avec 3 000 fichiers.

4voto

Christopher Stone Points 662

J'ai essayé l'approche de Josh en utilisant mdls et a trouvé un nombre surprenant de (nulls) pour kMDItemNumberOfPages.

J'ai donc changé de tactique et utilisé AppleScriptObjC pour compter directement les pages des fichiers PDF trouvés.

Le script sera exécuté directement à partir de l'application scriptEditeur.app ou à partir d'une applet script.

Il produira un rapport dans TextEdit qui ressemblera à ceci :

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

Cette exécution a pris à peu près 10 secondes sur mon MacBook Pro 17" Mid-2010 i7.

La ligne suivante doit être modifiée dans le script pour refléter correctement le répertoire cible sur le système de l'utilisateur :

property searchPath : "~/Downloads"

(Bien que je serais heureux de le faire fonctionner sur la fenêtre avant du Finder sur demande).

Le script est actuellement configuré pour être récursif dans le répertoire cible.

-------------------------------------------------------------------------------------------
# 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
-------------------------------------------------------------------------------------------

Comme cette créature n'a été que légèrement testée, je ne donne aucune garantie, mais j'en suis satisfait jusqu'à présent.

-ccs

0 votes

Intéressant - je n'ai pas eu de nulles. J'ai testé plusieurs combinaisons de fusions, un comptage manuel et l'approche de Josh, et les résultats ont été les mêmes. Cette méthode est cependant plus rapide, je peux le confirmer. Ce serait bien si l'on pouvait donner deux réponses "correctes".

0 votes

Juste un suivi - ce script est beaucoup plus rapide que le script ci-dessus. C'est aussi très bien d'avoir le nombre de pdfs comptés inclus et les erreurs éventuelles (je n'en ai pas eu sur plusieurs tests de centaines de fichiers).

0 votes

Je voudrais travailler sur la combinaison de nos scripts. En utilisant votre méthode de comptage, mais la mienne de sélection du répertoire, en ajoutant également la possibilité de sélectionner des documents spécifiques. De plus, créer une méthode différente pour montrer les résultats.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X