10.3: Create a virtual PDF printer

Nov 25, '03 10:00:00AM

Contributed by: ptwithy

I know that you can always select Save as PDF when printing, but I had a situation where I wanted to be able to print to PDF without having to go through the Print dialog. I suspected there was a simple way to do this with CUPS (the printing architecture underlying OS X). I found an article by Michael Goffiou that gave a simple shell script that would create a 'backend' for CUPS that does the trick. There are a few differences for Mac OS X, so I've modified his original script to fit. Here's what you need to do (in a Terminal):

  1. Copy the included script (in the main body of the hint) to /usr/libexec/cups/backend/pdf

  2. Make it executable by everyone:
     % sudo chmod a+x /usr/libexec/cups/backend/pdf
  3. (Optional) If you have the Acrobat Distiller PPD, put a copy in /usr/share/cups/model

  4. Restart the CUPS daemon, so it finds your new backend and model (sudo killall -HUP cupsd)
Now you can configure your virtual printer using the Printer Setup Utility.

[robg adds: This script has only been tested under Panther. If someone tests it under 10.2 and it works, please post a comment and I'll remove the "10.3:" designation.]

Hold down Option and click on the Add button. In the top list, select Advanced. For Device: choose PDF Writing. Give it a descriptive name (e.g., PDF Writer). For the device URI, use pdf://pathname, where pathname is where you would like the PDF file to be saved -- /tmp is a good choice as it gets cleaned out automatically when you restart. For the printer model, select Adobe (if you installed the Distiller PPD in step three above), otherwise leave it as Generic. Click on Add and you are ready to go!

The script creates a log file (/tmp/pdf.log) each time it prints, which might be helpful if something goes wrong.


#!/bin/sh
#
# Michael Goffioul
# Updated by P T Withington for Mac OS X

LOGFILE=/tmp/pdf.log
GSBIN=`which pstopdf`
FILENAME=

echo "Executable: $GSBIN" > $LOGFILE
echo "Arguments: |$1|$2|$3|$4|$5|$6|" >> $LOGFILE

# case of no argument, prints available URIs
if [ $# -eq 0 ]; then
  if [ ! -x "$GSBIN" ]; then
    exit 0
  fi
  echo "direct pdf \"Unknown\" \"PDF Writing\""
  exit 0
fi

# case of wrong number of arguments
if [ $# -ne 5 -a $# -ne 6 ]; then
  echo "Usage: pdf job-id user title copies options [file]"
  exit 1
fi

# get PDF directory from device URI, and check write status
PDFDIR=${DEVICE_URI#pdf:}
if [ ! -d "$PDFDIR" -o ! -w "$PDFDIR" ]; then
  echo "ERROR: directory $PDFDIR not writable"
  exit 1
fi

echo "PDF directory: $PDFDIR" >> $LOGFILE

# generate output filename
OUTPUTFILENAME=
if [ "$3" = "" ]; then
  OUTPUTFILENAME="$PDFDIR/unknown.pdf"
else
  OUTPUTFILENAME="$PDFDIR/${3//[^[:alnum:]]/_}.pdf"
fi

echo "Output file name: $OUTPUTFILENAME" >> $LOGFILE

# run ghostscript
if [ $# -eq 6 ]; then
  $GSBIN $6 -o $OUTPUTFILENAME >> $LOGFILE
else
  $GSBIN -i -o $OUTPUTFILENAME >> $LOGFILE
fi

# modify ownership and permissions on the file
#  - world readable
#  - owns to user specified in argument
chmod a+r $OUTPUTFILENAME
if [ "$2" != "" ]; then
  chown $2 $OUTPUTFILENAME
fi

exit 0

Comments (49)


Mac OS X Hints
http://hints.macworld.com/article.php?story=20031116190809396