22

I'm using Ghostscript library API (wrapping from C#) to print PDF documents from my application.
With the '-dFirstPage' and '-dLastPage' parameters I'm able to select an range of pages to be printed, but how about the total number of a PDF's pages?

It is not very nice to allow a user to select a page interval from 2 to 10 when, let me say, the PDF document has only 4 pages.

Consider that I'm using Ghostscript library through the gsapi_init_with_args API library call.

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
lorenzoff
  • 1,120
  • 3
  • 15
  • 32
  • 1
    PDFs MUST declare their number of pages in their metadata catalog. You could als run s.th. like *gs -q -c "(in.pdf) (r) file runpdfbegin pdfpagecount = quit"* to make Ghostscript count the pages. – Kurt Pfeifle Jan 28 '11 at 10:13
  • @pipitas Hello and thanks for your help; if i understud, i have to use "(in.pdf) (r) file runpdfbegin pdfpagecount = quit" as input parameter of a GS call? If yes, 'in.pdf' will be the input file but what about '(r)'? Thanks again. – lorenzoff Jan 28 '11 at 10:39
  • Just use '(r)' as is. It's a Ghostscript internal macro telling Ghostscript to read/run the '(in.pdf)' file... Yes, the only variable is `in.pdf` -- replace it with [path+]filename of your PDF. – Kurt Pfeifle Jan 28 '11 at 14:23

5 Answers5

40

Ghostscript can count and display the number of pages of a PDF on stdout. The commandline is

gswin32c ^
  -q ^
  -dNODISPLAY ^
  -c "(input.pdf) (r) file runpdfbegin pdfpagecount = quit" 

Here all the -c "..." stuff is a PostScript commandline snippet (using a few GS internal command extensions). And input.pdf is the PDF filename (could also be a full path like (c:/path/to/my.pdf)).

However, a better and faster tool for this kind of job would be to use pdfinfo (part of the XPDF-utilities, also available on Windows).


Update:

@ebyrob wants to know if one can modify my example command line so that it also displays the PDF in a single operation. Try this:

gswin32c ^
  -q ^
  -c "(input.pdf) (r) file runpdfbegin pdfpagecount =" ^
  -f input.pdf

Well, it's not a single operation -- it's just two different operations in a single commandline.

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
  • Could this be modified to read metadata while also displaying the PDF image in a single operation? (Say with `-sDEVICE=display` and friends specified) And also, when reading file from `stdin`? (ie: gswin32 filename of `-`) Running just: `-c "pdfpagecount"` seemed to give me an "operation doesn't exist" error. Including `runpdfbegin` game me invalid file name. –  Mar 26 '14 at 13:18
  • @ebyrob: you need every single character in my command example (you may only change '*input.pdf*' to a different existing filename or -path. You can't just skip any part as you feel like... – Kurt Pfeifle Mar 26 '14 at 22:53
  • I was thinking something like: `gswin64c - -c "currentfile runpdfbegin pdfpagecount ==" < input.pdf` would help. But, runpdfbegin uses `setfileposition` which isn't supported, apparently, by `stdin` or `currentfile`. Working entirely in memory with the DLL interface makes reading from the filesystem a bit troublesome. my "invalid filename" came from `(%stdin) runpdfbegin` and variations with `file` command. Basically I couldn't specify `stdin` to `file` or `runpddfbegin` successfully. –  Mar 27 '14 at 15:13
  • Looks like `%` was being removed by command line, `%%` works in NT batch script. So, I'm back to `setfileposition` breaking `runpdfbegin` for anything like stdin or in-memory operation. –  Mar 31 '14 at 19:42
  • @KurtPfeifle I think I found something that might work here: http://bugs.ghostscript.com/show_bug.cgi?id=691739 Of course, I'm still going to have to skip the `input.pdf` parts... Did I forget to mention in my first comment that I wanted to read from `stdin`? –  Mar 31 '14 at 20:55
  • Is there a way to capture the output of this command (meaning the number of pages)? I'm trying to run this from within python using the ghostscript package, but it just runs and completes successfully, I would like to write it to a variable or a file. – Ran Lottem Jan 17 '18 at 10:26
  • If you are getting /invalidfileaccess error see Ger Hobbelt's answer here: https://stackoverflow.com/a/61310729/8542816 – Sam Tigle Nov 05 '20 at 11:05
4

For people having issues in ghostscript >9.50 add --permit-file-read=input.pdf

2

I tried to make this script:

gswin32c ^
  -q ^
  -c "(input.pdf) (r) file runpdfbegin pdfpagecount =" ^
  -f input.pdf

work in a c# wrapped solution and kept getting error "/undefinedfilename". In this case ensure that your filepath has Slashes "/" as DirectorySeperator and not Backslashes "\". I know Kurt Pfeifle already wrote it, but it happened to me i just overlooked it.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Sam Tigle
  • 393
  • 3
  • 14
1

In Windows systems:

"path to gs exec" -q -dNODISPLAY -dNOSAFER --permit-file-read="path to your file" -c "(""path to your file"") (r) file runpdfbegin pdfpagecount = quit"

Remarks:

  • Just change where is 'path to...' with your path, leave the rest as is.
  • On the -c path you must use double slashes or unix like ones. Ex: C:\\youfile.pdf (good), C:/youfile.pdf (good), C:\yourfile.pdf (bad).

Example:

  • path: C:\Temp\Some Folder\myFile.pdf
  • gs path: C:\Temp\Some Folder\gs\bin\gswin64c.exe
  • path -c 1: C:\\Temp\\Some Folder\\myFile.pdf
  • path -c 2: C:/Temp/Some Folder/myFile.pdf

Commands:

"C:\Temp\Some Folder\gs\bin\gswin64c.exe" -q -dNODISPLAY -dNOSAFER --permit-file-read="C:\Temp\Some Folder\myFile.pdf" -c "(""C:\\Temp\\Some Folder\\myFile.pdf"") (r) file runpdfbegin pdfpagecount = quit"

"C:\Temp\Some Folder\gs\bin\gswin64c.exe" -q -dNODISPLAY -dNOSAFER --permit-file-read="C:\Temp\Some Folder\myFile.pdf" -c "(""C:/Temp/Some Folder/myFile.pdf"") (r) file runpdfbegin pdfpagecount = quit"
ietsira
  • 29
  • 4
0

To sum up some of the above separate comments for windows users to avoid needing to alter between / and \\ , to show the total number of pages can be set as a shortcut for drag and drop or "sendTo", by first switching to a working directory.

@echo off & cd /d "%~dp1" & "C:\path to gs\bin\gs.exe" -q --permit-file-read="%~nx1" -c "(%~nx1) (r) file runpdfbegin pdfpagecount = quit" & pause

where gs.exe is one of the windows c(onsole) variants gswin32c.exe or gswin64c.exe

  • The cd /c "%~dp1" will switch console to quoted file drive path
  • The full quoted path to "GSwin..c.exe" calls it safely and remotely
  • -q will suppress (not show) the start message
  • since version 9.5+ the --permit-file-read="file name" is advised / required
  • -c "(%~nx1) does not need the quotes for name.xtension
  • if running a cmd as a shortcut, pause is required to see the result

beware only use on files you trust as your overriding GS -dSAFER restrictions.

enter image description here

K J
  • 8,045
  • 3
  • 14
  • 36