The Bash logo

Print double-sided documents with this Bash script

0

Last Updated on November 24, 2024 by Jim Hall

I have an old laser printer at home that I use occasionally. My Hewlett Packard LaserJet Pro CP1525nw Color Printer is a great workhorse that prints reliably and in color. While I don’t use it all the time, this printer is useful when I need to print a proof of an article, or make a paper copy of an important document.

My only limitation with this printer is that it can only print single-sided pages. If you want to print double-sided pages, you need to set up a custom print job to that yourself: you print the odd-numbered pages, then reload the pages into the printer and print the even-numbered pages:

Printing odd-numbered pages from LibreOffice
Printing odd-numbered pages from LibreOffice

For example, to print a 4-page document, I have to print pages 1 and 3. Then I reload the pages face-down in the tray to print the even pages — but I need to print the even pages in reverse order: pages 4 and 2. It’s not so bad for a short document, but it’s a pain to get right when printing a longer document that might be 20 pages.

Automating the steps

To make things easier, I wrote a short Bash script that automates the process of printing in “duplex” on a printer that only prints on one side at a time.

Whenever I need to print a document in 2-sided mode, I first convert the file to PDF. This is easy to do if the file is not already in PDF format. For example, you can use the “File > Export As > Export as PDF” feature in LibreOffice Writer, or you can do it right from the command line with this command:

$ libreoffice --headless --convert-to pdf file.odt

Once I have the file in PDF format, my Bash script uses the lpr command with options to first print the odd-numbered pages in the document, then display a prompt so I know to reload the pages into the printer, then uses lpr a second time to print the even-numbered pages.

Even or odd?

The only tricky part is determining the page count, so I know if the document has an even number of pages (which is easy to print double-sided) or an odd number of pages (the last page doesn’t need to be loaded back into the printer).

To determine the page count, I use the pdfinfo command. This generates useful information about a PDF document, including the page count. For example, this document is 5 pages long:

$ pdfinfo wordle.pdf
Creator:         Writer
Producer:        LibreOffice 24.2
CreationDate:    Sat Nov 16 16:20:22 2024 CST
Custom Metadata: no
Metadata Stream: no
Tagged:          yes
UserProperties:  no
Suspects:        no
Form:            none
JavaScript:      no
Pages:           5
Encrypted:       no
Page size:       612 x 792 pts (letter)
Page rot:        0
File size:       65861 bytes
Optimized:       no
PDF version:     1.7

That output is very easy to parse with awk. To get the page count, I use awk to look for the Pages: line, and print the second ($2) field on the line:

$ pdfinfo wordle.pdf | awk '/^Pages:/ {print $2}'
5

To figure out if this is an even or odd number, I use the modulo (%) arithmetic operator to divide by 2 and print the remainder. For an odd number, the modulo by 2 will always be 1; for an even number, it will always be zero. I can automate this in Bash using a few lines:

#!/bin/bash

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

if [ $(( pages % 2 )) -eq 1 ] ; then
  echo "odd"
else
  echo "even"
fi

For my 5-page file, this prints “odd”. Knowing if the page count is even or odd makes it easier to make a suitable prompt when I need to re-load pages into the printer.

Writing the script

Now I can put it all together. My script first prints the odd-numbered pages (1, 3, 5, ..) then waits for the printer to finish printing before displaying a prompt for me to re-load the pages into the printer. If the document has an odd number of pages, it also reminds me to remove the last page. With the pages loaded back into the printer, the script prints the even-numbered pages (2, 4, 6, ..)

#!/bin/bash

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

echo "Printing odd pages..."
lpr -P "HP_LaserJet_CP1525nw" -o page-set=odd "$1"

# add a delay to give the printer time to finish:
sleep $pages

echo "Put the pages back into the printer IN THE EXACT ORDER"
echo "face-down in the tray."

if [ $(( pages % 2 )) -eq 1 ] ; then
  echo "Remove the last page -- this document has an odd number of pages."
fi

echo -n "Print Enter when ready:"
read x

echo "Printing even pages..."
lpr -P "HP_LaserJet_CP1525nw" -o page-set=even -o outputorder=reverse "$1"

Save this as a new script on your system, and make it executable with chmod +x. On my system, I called it print-duplex. For example, when printing a 5-page document, I see this output:

$ print-duplex wordle.pdf
Printing odd pages...
Put the pages back into the printer IN THE EXACT ORDER
face-down in the tray.
Remove the last page -- this document has an odd number of pages.
Print Enter when ready:
Printing even pages...

Leave a Reply