Print double-sided documents at home with this simple Bash script

Use this script and save yourself the hassle and wasted paper of trying to manually load and print double-sided documents.
74 readers like this.
bash logo on green background

Opensource.com

We have a laser printer at home. This Hewlett Packard LaserJet Pro CP1525nw Color Printer is an older model, but it has been a great workhorse that prints reliably and in color. I put it on our home network a few years ago using our Raspberry Pi as a print server.

The LaserJet has been a great addition to my home office. Since I launched my company last year, I have relied on this little laser printer to print handouts and other materials for client meetings, workshops, and training sessions.

My only gripe with this printer is that it prints single-sided only. If you want to print double-sided, you need to set up a custom print job to do it yourself. That's inconvenient and requires manual steps. In LibreOffice, I need to specifically set up the print job to print the odd-numbered pages first, then reload the paper before printing the even-numbered pages on the other side—but in reverse order.

LibreOffice print dialog

If I need to print a PDF that someone has sent me, the process is the same. For a four-page document, I first need to print pages 1 and 3, then reload the paper and print pages 2 and 4 in reverse order. In the GNOME print dialog, you need to select "Page Setup" to print odd pages or even pages.

Gnome print dialog

Gnome page setup

Regardless of how I print, the overall process is to print the odd-numbered pages, reload the stack of printed pages into the paper tray, then print the even-numbered pages in reverse order. If I'm printing a four-page document, printing the even-numbered pages in reverse order means page 4 prints on the back of page 3 and page 2 prints on the back of page 1. Imagine my frustration in those few instances when I forgot to select the option to print in reverse order when printing the even-numbered pages and ruined a long print job.

Similarly, it's easy to forget how to deal with documents that have an odd number of pages. In a five-page document, you first print pages 1, 3, and 5. But when you reload the printed pages into the printer, you don't want page 5. Instead, you only want to load pages 1 and 3. Otherwise, page 4 will print on the back of page 5, page 2 will print on the back of page 3, and nothing gets printed on the back of page 1.

To make things easier and more reliable, I wrote a simple Bash script that automates printing duplex. This is basically a wrapper to print odd-numbered pages, remind me to reload the pages (and remove the last page if needed), then print the even-numbered pages.

Whenever I need to print a document as duplex, I first convert the document to PDF. This is very easy to do. In LibreOffice, there's a toolbar icon to export directly as PDF. You can also navigate under File— Export As—Export as PDF to do the same. Or in any other application, there's usually a Save to PDF feature. When in doubt, GNOME supports printing to a PDF file instead of a printer.

Libre Office toolbar

Export as PDF

How it works

Once I've saved to PDF, I let my Bash script do the rest. This really just automates the lpr commands to make printing easier. It prints odd pages first, prompts me to reload the paper, then prints the even pages. If the document has an odd number of pages, it also reminds me to remove the last page when I reload the printed pages. It's pretty simple.

The only "programming" part of the script is determining the page count, and figuring out if that's an even or odd number. Both of those are easy to do.

To determine the page count, I use the pdfinfo command. This generates useful info about a PDF document. Here's some sample output:

$ pdfinfo All\ training\ -\ catalog.pdf
Creator:        Writer
Producer:       LibreOffice 6.3
CreationDate:   Fri Oct 18 16:06:07 2019 CDT
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          11
Encrypted:      no
Page size:      612 x 792 pts (letter)
Page rot:       0
File size:      65623 bytes
Optimized:      no
PDF version:    1.5

That output is very easy to parse. To get the page count, I use an AWK one-line script to look for Pages: and print the second field.

pages=$( pdfinfo "$1" | awk '/^Pages:/ {print $2}' )

To figure out if this is an odd or even number, I use the modulo (%) arithmetic operator to divide by two and tell me the remainder. The modulo of two will always be zero for an even number, and one for an odd number. I use this simple test to determine if the document has an odd number of pages, so I'll need to remove the last page before printing the rest of the document:

if [ $(( $pages % 2 )) -ne 0 ] ; then

With that, writing the print-duplex.sh Bash script is a simple matter of calling lpr with the correct options to send output to my printer (lpr -P "HP_LaserJet_CP1525nw"), to print odd-numbered pages (-o page-set=odd) or even-numbered pages (-o page-set=even), and to print in reverse order (-o outputorder=reverse).

Bash script

#!/bin/sh
# print-duplex.sh
# simple wrapper to print duplex

cat<<EOF
$1 ($pages pages)
-------------------------------------------------------------------------------
Printing odd pages first
Please wait for job to finish printing...
-------------------------------------------------------------------------------
EOF

lpr -P "HP_LaserJet_CP1525nw" -o page-set=odd "$1"
sleep $pages

cat<<EOF
===============================================================================
Put paper back into the printer in EXACT OUTPUT ORDER (face down in tray)
then press ENTER
===============================================================================
EOF

pages=$( pdfinfo "$1" | awk '/^Pages:/ {print $2}' )

if [ $(( $pages % 2 )) -ne 0 ] ; then
  echo '!! Remove the last page - this document has an odd number of pages'
fi

echo -n '>'
read x

cat<<EOF
-------------------------------------------------------------------------------
Printing even pages
Please wait for job to finish printing...
-------------------------------------------------------------------------------
EOF

lpr -P "HP_LaserJet_CP1525nw" -o page-set=even -o outputorder=reverse "$1"

 

What to read next
photo of Jim Hall
Jim Hall is an open source software advocate and developer, best known for usability testing in GNOME and as the founder + project coordinator of FreeDOS.

8 Comments

Hi Jim, nice article. One minor error: `pages` variable needs to be set at the beginning.

Oops, that is my error when prepping this for an article. I moved the pages= definition down to where it gets used for the B sides (thought that would make it easier to read) but I forgot there's an echo statement at the start that references $pages, and a sleep command up above that sleeps for the number of seconds equal to the number of pages.

Sorry about that. Yes, the pages= definition should be at the top of the script.

I would like to suggest a modification. I routinely print double-sided on a Brother B&W laser printer. If I print the EVEN pages first, I don't need to worry about an "extra" odd page at the end. That eliminates the need to remove the odd page from the stack before printing the other side.

That's a good idea. I'll try that. Thanks!

In reply to by Edouard Piche (not verified)

it works but, you will need to reorder all the pages after (the first page of stack will be page 2). To work properly you will need to print even pages first in reverse order and then print odd pages, but if you have odd number of pages, you still need to add a blank page, before print the other side.

In reply to by Edouard Piche (not verified)

Hi Jim,

This is great - I too have a simplex laser printer ... I took your script as a starting point and did this. I also took the above comments of printing the even pages first which further simplies the script.

This script can print any # of documents requested by the user.

https://gist.github.com/walterjwhite/4da9fdc077dbbbd8ac855eb66edae1e1

Thanks,

Walter

1 If it's a bash script, you should use bash on the hash bang line

2 bash can use arithmetic expressions as conditions, so 'if $(( .... )); then ... ; fi' would do the job

In order to avoid removing a page from printer (manual work...) just print a blank page.

Instead of :

if [ $(( $pages % 2 )) -ne 0 ] ; then
echo '!! Remove the last page - this document has an odd number of pages'
fi

Change it to :

if [ $(( $pages % 2 )) -ne 0 ] ; then
blank_page=$(mktemp)
echo " " > $blank_page
lpr $blank_page
rm $blank_page
fi

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.