Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

A simple way to create PDFs from the command line UNIX
I have used many different methods over the years to print documents to PDFs from the command line. Some have been complicated sequences of pipes to and from groff, others required TeX, and occasionally I set up a "virtual" printer, simply to print to file. I recently read documentation for cups-pdf, however, and found that cupsfilter command is sufficient for most of my own tasks in its bare form!

For example, to print 80-column ASCII plaintext (the majority of my code), I can use this:
$ cupsfilter foo.txt > foo.pdf 
If you find the output of that command a bit verbose (as I do), you can send the errors silently to the null device using this version:
$ cupsfilter foo.txt > foo.pdf 2> /dev/null
There are many ways to wrap this simple command even more conveniently, but I'll omit those here for now. The reason this method is ideal is because it uses built-in routines in OS X; any time you can take advantage of these, do, because many of the core technologies are significantly faster and more secure than third-party alternatives.

Of course, your mileage may vary :-).

[robg adds: cupsfilter PDF conversions work in at least 10.5 and 10.6, and I suspect in earlier OS X releases.]
    •    
  • Currently 3.16 / 5
  You rated: 2 / 5 (25 votes cast)
 
[17,906 views]  

A simple way to create PDFs from the command line | 10 comments | Create New Account
Click here to return to the 'A simple way to create PDFs from the command line' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
A simple way to create PDFs from the command line
Authored by: lurch99 on Dec 08, '09 09:06:51AM
I'm not sure if this is any easier or better than using "pstopdf", for example the following saves the "man" page of dscl:
# man -t dscl | pstopdf -i -o ~/Desktop/dscl.pdf


[ Reply to This | # ]
A simple way to create PDFs from the command line
Authored by: bfr00 on Dec 16, '09 04:50:43PM

The pstopdf method seems interesting but then you have to generate the PS. And groff seems to be the way to do that - but groff is a massively complicated disaster and I can't even figure out how to preserve newlines. So maybe cupsfilter would be better if we can control fonts and maybe also scaling.
Just as an example, how wouid you get a PDF with multilines from this:
ls -1 | groff -Tps | pstopdf -i -o ~/desktop/ls.pdf

Edited on Dec 16, '09 04:52:17PM by bfr00



[ Reply to This | # ]
Okay for a quick-n-dirty PDF, but...
Authored by: snuggles on Dec 08, '09 10:59:37AM
...the results are less than ideal. The font used for rendering the text appears to be Monaco at some large point size. Also, cupsfilter has no way of creating page numbers, generating useful headings, or performing word-wrap on long lines. Here's another approach, also using utilities built into Mac OS X, that produces much nicer output:
#!/bin/bash
enscript --word-wrap -p - "$1" | gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$2" -
The enscript utility has an obscene number of options, so the possibilities for formatting font, margins, headings, etc. of the PDF file are nearly endless.

[ Reply to This | # ]
Okay for a quick-n-dirty PDF, but...
Authored by: thinkyhead on Dec 12, '09 08:02:22PM

Nice, as is the script below, but my Snow Leopard system doesn't have gs (GhostScript) installed. Is this an optional part of SL or do we need to get it elsewhere?

---
|
| slur was here
|



[ Reply to This | # ]
And here's a more sophisticated version...
Authored by: snuggles on Dec 10, '09 10:45:50AM
...taking advantage of bash, PHP, enscript, and gs (all part of OS X) to create a nicely-formatted PDF:
#!/bin/bash

MOD_TIME_EPOCH=`stat -f %m $1`
MOD_TIME_FMT=`date -r $MOD_TIME_EPOCH +'%a %e %b %Y @ %R %Z' | sed 's/ [ ]*/ /g'`
FULL_NAME=`php -r "echo realpath('$1');"`

mkdir -p $HOME/.enscript

# Create temporary "fancy header" file for enscipt.
cat > $HOME/.enscript/tmp_txt2pdf.hdr <<EOF
% -- code follows this line --
%Format: last_mod_timestr $MOD_TIME_FMT
%Format: pagestr page \$V$%/$=
%HeaderHeight: 30
%FooterHeight: 30
/Helvetica /helvetica-encoded MF
/Helvetica-10-Regular /helvetica-encoded findfont 10 scalefont def
/Helvetica-Bold /helvetica-bold-encoded MF
/Helvetica-10-Bold   /helvetica-bold-encoded findfont 10 scalefont def
/new_marg 4 def
/do_header {
  gsave
    Helvetica-10-Bold setfont
    d_footer_x d_footer_w add pagestr stringwidth pop sub
    new_marg sub
    d_footer_y 7 add moveto pagestr show
    Helvetica-10-Bold setfont
    d_footer_x new_marg add d_footer_y 7 add moveto last_mod_timestr show
    Helvetica-10-Bold setfont
    d_header_x d_header_w 2 div add fname stringwidth pop 2 div sub
    d_header_y 16 add moveto fname show
  grestore
} def
EOF

enscript --fancy-header=tmp_txt2pdf --word-wrap -p - "$FULL_NAME" | gs -q \
    -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$2" -

rm -f $HOME/.enscript/tmp_txt2pdf.hdr
Save this in your somewhere in your path as 'txt2pdf', make sure it's executable, and use a follows:
txt2pdf input_file.txt output_file.pdf
The contents of the text file will be rendered in word-wrapped 10-point Courier with headers and footers in 10-point bold Helvetica: the filename (including full path) centered in the header, file modification date and time on the left side of the footer, and "page x/y" on the right side of the footer.

Edited on Dec 10, '09 10:53:32AM by snuggles


[ Reply to This | # ]
correction
Authored by: snuggles on Dec 14, '09 02:10:55PM
Commenter "slur" is correct in noting that I was mistaken about gs being part of the default Mac OS X installation; it's clearly not. On my system, it's found under '/usr/local/bin' and probably ended up there when I installed MacTeX many months ago. Fortunately, the fix actually simplifies things a bit: replace gs with the BSD command pstopdf, which really is part of Mac OS X (or Snow Leopard, at least). The simple version then becomes:
#!/bin/bash
enscript --word-wrap -p - "$1" | pstopdf -i -o "$2"
And the longer version becomes:
#!/bin/bash

MOD_TIME_EPOCH=`stat -f %m $1`
MOD_TIME_FMT=`date -r $MOD_TIME_EPOCH +'%a %e %b %Y @ %R %Z' | sed 's/ [ ]*/ /g'`
FULL_NAME=`php -r "echo realpath('$1');"`

mkdir -p $HOME/.enscript

# Create temporary "fancy header" file for enscipt.
cat > $HOME/.enscript/tmp_txt2pdf.hdr <<EOF
% -- code follows this line --
%Format: last_mod_timestr $MOD_TIME_FMT
%Format: pagestr page \$V$%/$=
%HeaderHeight: 30
%FooterHeight: 30
/Helvetica /helvetica-encoded MF
/Helvetica-10-Regular /helvetica-encoded findfont 10 scalefont def
/Helvetica-Bold /helvetica-bold-encoded MF
/Helvetica-10-Bold   /helvetica-bold-encoded findfont 10 scalefont def
/new_marg 4 def
/do_header {
  gsave
    Helvetica-10-Bold setfont
    d_footer_x d_footer_w add pagestr stringwidth pop sub
    new_marg sub
    d_footer_y 7 add moveto pagestr show
    Helvetica-10-Bold setfont
    d_footer_x new_marg add d_footer_y 7 add moveto last_mod_timestr show
    Helvetica-10-Bold setfont
    d_header_x d_header_w 2 div add fname stringwidth pop 2 div sub
    d_header_y 16 add moveto fname show
  grestore
} def
EOF

enscript --fancy-header=tmp_txt2pdf --word-wrap -p - "$FULL_NAME" | pstopdf -i -o "$2"

rm -f $HOME/.enscript/tmp_txt2pdf.hdr
It's worth noting that the seemingly superfluous % -- code follows this line -- seems to be a required part of enscript header files.

[ Reply to This | # ]
A simple way to create PDFs from the command line
Authored by: fulmar2 on Dec 17, '09 05:18:58PM
Thanks for this hint! I tried it, and got it to work on a text file - it it possible to use cupsfiler on a MS Word file (for example)?

[ Reply to This | # ]
A simple way to create PDFs from the command line
Authored by: LoadedMind on Feb 19, '10 12:50:46PM

You'd have to modify the script to account for the extra data Word and TextEdit adds aka rich text.



[ Reply to This | # ]
A simple way to create PDFs from the command line
Authored by: LoadedMind on Feb 19, '10 12:49:43PM

fulmar2> You'd have to modify the script to accommodate for the "rich text" formatting that's added by Word and TextEdit



[ Reply to This | # ]
A simple way to create PDFs from the command line
Authored by: cyclox on May 18, '10 02:59:12PM

Thanks for posting this. I used to use enscript back in the days of NeXT and hadn't bothered to try it under MacOS.



[ Reply to This | # ]