Lpskim is a universal SYSV interface script for CUPS designed for filtering and manipulation of text print jobs based on a printcap-style configuration file.

Download lpskim


lpskim.pl - A generalized SYSV interface script for CUPS.


Lpskim.pl is designed to be inserted as an interface script for CUPS. To do so for a given queue ZIGGY:

 lpadmin -p ZIGGY -i /path/to/lpskim.pl

This will create a copy of lpskim.pl named for the queue, in the CUPS interfaces directory, typically /etc/cups/interfaces (akin to how lpadmin copies PPDs to /etc/cups/ppd).


Configuration is done on a per-queue basis, in file /etc/cups/lpskim.conf. Each line of the file corresponds to one queue, followed by configuration directives for that queue. If there is no configuraiton for a queue (or no config file at all), the job will simply pass through to the backend with no modification.

A configuration line is similar to /etc/printcap, in that the queue name is followed by a |, followed by colon-delimited directives. Blank lines and comment lines beginning with # are ignored. Spaces around | or : do not matter. Options that take values can appear more than once, and will be applied in the order they appear in the config file.

Configuration Directives


Append given string(s) to print job.

Ex: append=testing123\n


Print job only if it contains printable characters (ascii >= 32 && ascii < 127) otherwise cancel the job with exit value 5.


If job text matches pattern(s), load alternate configuration. First match wins when multiple conf_switch patterns are given.

Ex: conf_switch=/123456/=ZIGGY_1


Copy text at source line or line,col,length range and paste or replace at destination line or line,col location as specified.

Ex: copy=8=paste=11

Ex: copy=8,71,8=replace=11,51


Cut text at source line or line,col,length range and paste or replace at destination line or line,col location as specified.

Ex: cut=8=replace=11

Ex: cut=8,71,8=paste=11,51


Print debugging output to /tmp/QUEUE.debug.


Delete text at destination line or line,col,length range as specified.

Ex: delete=8

Ex: delete=8,71,8


Apply regex substitution(s) to job.

Ex: filter=s/testing123/testing456/g


Insert string at destination line or line,col location as specified.

Ex: insert=8=testing123\n

Ex: insert=8,50=testing123


When respooling, lp option(s) to apply. Only applicable when respooling.

Ex: lpoption=cpi=17


Prepend given string(s) to print job.

Ex: prepend=\e(6N\e(s0p12h6v8s0b0T\e&l7C\e&a9L


Respool print job to given QUEUE(s).

Ex: respool=ZAGGY


Save printjob to $ENV{TMPDIR}/$jid-$uid-lpskim-$$.cups

Example Configurations

An example (one-line) configuration for queue ZIGGY, debugging on, saving job output, checking whether job is printable, applying three filters to the job, respooling to another queue with several lp options:

 ZIGGY | debug : save_job : check_printable : filter=s/4/FOUR/g : \ 
 filter=s/6/SIXES/g : filter=s/\n/\n\r/g : respool=KEL210 : \ 
 lpoption=landscape : lpoption=cpi=17 : lpoption=lpi=8.75 : \ 
 lpoption=page-left=54 : lpoption=page-top=54

Another example for queue ZIGGY, this one prepending a PCL string, appending a form feed, some filtering, and respooling to another queue:

 ZIGGY | prepend=\e(6N\e(s0p12h6v8s0b0T\e&l7C\e&a9L : append=\f : \ 
 filter=s/4/FOUR/g : filter=s/6/SIXES/g : respool=KEL210 : lpoption=raw

An example on ZIGGY that applies options and respools, unless certain strings match in the conf_switch to flip over to other configs for specific print jobs, essential for situations when one queue handles different kinds of jobs and they will reliably match:

 ZIGGY | debug : save_job : conf_switch=/\n\n\n\n\n/=ZIGGY_1 : \ 
 conf_switch=/123456/=ZIGGY_2 : respool=KEL210 : lpoption=landscape : \ 
 lpoption=cpi=17 : lpoption=lpi=8.75 : lpoption=page-left=54
 ZIGGY_1 | debug : save_job : prepend=\f : respool=KEL210 : \ 
 lpoption=landscape : lpoption=cpi=17 : lpoption=lpi=8.75

 ZIGGY_2 | debug : save_job : filter=s/\f//g : respool=KEL210 : \ 
 lpoption=cpi=40 : lpoption=page-top=228

Example for queue ZIGGY making use of insert and delete, as well as cut to move a section of text from one line to another, using replace rather than paste so as not to throw off alignment of subsequent text on that line:

 ZIGGY | debug : save_job : insert=9=\n : delete=15 :  cut=8,71,8=replace=11,51 : respool=KEL210 : lpoption=cpi=10.25


Not all escaped strings work in appends, prepends, matches and substitutions. Currently, only \e \f \n \r work as expected.

Text manipulation commands (filter, insert, delete, cut, copy, paste, replace) are done in one pass, and are conducted line-by-line. This means that paste or replace actions must ultimately be sourced from cut or copy actions earlier in the document, and that only one action of each type is permitted per line.

Text manipulation commands can only place text at columns where text already exists. Example, a line X consisting of nothing but a new line that receives an insert, paste, or replace at column 50 will not actually place it there, instead placing it at the beginning of the line. Actually doing so would require defining a filler character (such as space).


lpskim 1.00 (20131202)

- Initial release.