Mass alteration of PS files with Vim

Recently I’ve been looking into Fortran, a language I haven’t used in ages. (Fortran 90 and 95 seem to address many of the problems that made Fortran 77 and earlier such messes.) I discovered that PDF versions of the Numerical Recipes books are available for download. I downloaded the many files that constitute the F77 and F90 versions and decided that, to save paper, I’d like to print them 2-up, double-sided. For this, I needed to convert the files to PostScript and use the psnup utility to create a new set of files in the 2-up format.

The conversion program I used was pdftops, a command line tool that’s part of the xpdf package. Because there were so many files, I made a Perl one-liner to do them all at once:

perl -e 'for(@ARGV){`pdftops $_`}' *.pdf

No doubt this could be done directly with shell commands, but I’m more comfortable with Perl. Now I had a set of PostScript files ready for reformatting.

After a bit of experimentation with psnup, I found two problems:

  1. The default layout of psnup -2 made the text too small and wasted a lot of the sheet on whitespace. Changing to psnup -2 -s.85 reduced the whitespace and gave text of the right size, but the printed area was pushed over too far to the left—some of the text would be cut off.

  2. The PDFs have a copyright notice in the right margin of each page, which is terribly distracting. I have no intention of violating the restrictions they impose (one paper copy per user, no hosting of the PDFs on a server), but I don’t want to see those restrictions on every damned page of the book. Fortunately, the restrictions don’t say anything about the form in which the book can be printed. In particular, they don’t say that the restrictions themselves need to be printed.

I made the set of 2-up-formatted files with the one-liner

perl -e 'for(@ARGV){$b=substr($_,0,-3);`psnup -2 -s.85 $_ $b-2up.ps`}' *.ps

and started digging into the PostScript of the 2-up files to see how I could solve the two problems.

With a bit of trial and error, I found that the first problem could be solved by changing the line

562.235294 -0.000000 translate

to

652.235294 -0.000000 translate

wherever it appeared (once for each logical page) in each 2-up-formatted file. This shoved all the text 90 points to the right so it wouldn’t be cut off. I opened all the 2-up PostScript files in Vim with vim *2up.ps and executed

:bufdo! g/translate/ s/^562/652/

which worked because the lines I wanted to change were the only lines that contained the word “translate.”

The second problem was only slightly harder to fix. Each logical page had, I discovered, a 23-line section that printed the copyright notice. The first line of the notice contained the word “NUMERICAL” in all-caps. This word never appeared in all-caps anywhere else. So the command

:bufdo! g/NUMERICAL/ .,+22s/^/%/

commented out the copyright notice in all the files. A quick :wall to save the changes in all the files and a :q to quit and my work was done. I checked a couple of files with ghostview to make sure the changes had worked and then sent the whole batch off to the duplex printer.

The great thing about this exercise was how easy it was to accomplish with Unix/Linux tools. Yes, it was fortunate that I knew a little PostScript and knew which formatting tools to use. And yes, there was some trial and error to learn what formatting looked good. But once it was worked out, that same formatting was applied to over 200 files with just a handful of commands. The tedium of doing this in a point-and-click environment—assuming that the tools to do so exist—would have been so extreme that I would have given up.