Monday, February 17, 2014

wkhtmltopdf converts HTML to PDF

Most - if not all - new electronic devices don't come with printed manuals. For the Sony laptop SVF15A1 I bought, I had to go to the Sony web site to access the user guide. The user guide is composed of many individual HTML pages. This posted a problem for me because I wanted to convert some HTML pages to PDF documents for easier off-line access.

Modern web browsers, such as Chrome and Firefox, have the built-in print to PDF feature.

For Chrome,

  1. Navigate to the HTML page, right click, and select Print.
  2. Select Save as PDF to be the Destination.
  3. Click Save, and select the output directory to save in.

Note that the output PDF file is automatically named User Guide _ Using the Touch Pad.pdf. I did not have to manually make up the file name because the default name was extracted from the HTML page content. This saves so much time for users that it becomes a major advantage for using the browser print function to do the conversion.

If you prefer a command-line solution, wkhtmltopdf is a simple yet powerful tool to convert HTML to PDF.

$ wkhtmltopdf -s Letter http://docs.esupport.sony.com/pc/SVF14A1_15A1_series/EN/contents/TP0000053442.html UserGuideTouchPad.pdf
Loading page (1/2)
Printing pages (2/2)
Done               

wkhtmltopdf can convert HTML files stored on the local hard drive or over the Internet. The above example specifies a URL from the Sony support web site.

By default, the pages in the output PDF file are of the size A4. North American users may specify the page size Letter using the -s parameter.

The last parameter to wkhtmltopdf is the mandatory output file name. Despite its rich set of parameters, it is missing the feature to automatically name the output file. To harness the full power of wkhtmltopdf, please refer to the man page.

If you want to merge individual PDF files, please see my posts on pdftk, and ImageMagick.

Saturday, February 8, 2014

Find out when a package was last installed or updated

If you administer a Linux computer, you may occasionally ask when a software package was last installed or updated on your system.

For a Red-Hat-based operating system - Centos, Fedora, RHEL, etc - getting the answer is a simple task of querying the RPM database. The RPM database stores, among other things, the last install date of rpm packages.

To query information about the curl package:

$ rpm -qi curl
Name        : curl
Version     : 7.29.0
Release     : 7.fc19
Architecture: i686
Install Date: Sun 11 Aug 2013 03:55:52 PM PDT
Group       : Applications/Internet
Size        : 529869
License     : MIT
Signature   : RSA/SHA256, Sun 23 Jun 2013 09:26:17 AM PDT, Key ID 07477e65fb4b18e6
Source RPM  : curl-7.29.0-7.fc19.src.rpm
Build Date  : Sat 22 Jun 2013 02:46:47 PM PDT
Build Host  : buildvm-11.phx2.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://curl.haxx.se/
Summary     : A utility for getting files from remote servers (FTP, HTTP, and others)
Description :
...

Note the Install Date for curl is Sun 11 Aug 2013 03:55:52 PM PDT. If curl was installed and subsequently updated, the stored Install Date is the update date, not the first install date.

If you run a Debian-based OS - Debian, Ubuntu, Mint, etc - you have to work harder to get the answer. The Debian package manager (dpkg) does not actually store the install date of packages in its database. However, you can still find it out using either of the following procedures.

  • Search the dpkg log files

    The following example reveals the last update time for the curl package (2014-02-04 11:40:55).

    $ grep 'status installed curl:' /var/log/dpkg.log* 
    /var/log/dpkg.log:2014-02-04 11:40:55 status installed curl:amd64 7.26.0-1+wheezy8
    /var/log/dpkg.log.1:2014-01-08 10:06:50 status installed curl:amd64 7.26.0-1+wheezy7
    

    There is a catch with this approach. You cannot search merely the current dpkg log. Depending on when the package was installed or last updated, the dpkg log may already be rotated out. Hence, the asterisk in dpkg.log*. It matches dpkg.log, dpkg.log.1, dpkg.log.2, etc. However, if the package was installed a long time ago, the log file you are looking for may be already auto-deleted from the system.

  • Look for the last modified timestamp of the package's file list.

    When a package is installed or updated, its corresponding file list in /var/lib/dpkg/info/ is overwritten with the latest information. For instance, /var/lib/dpkg/info/curl.list contains a list of file names that are installed by the curl package.

    The last modified timestamp of curl.list gives you a fairly accurate time of when curl was last installed/updated.

    $ ls -l /var/lib/dpkg/info/curl.list
    -rw-r--r-- 1 root root    584 Feb  4 11:40 /var/lib/dpkg/info/curl.list
    

    Again, if curl was updated after the initial install, the timestamp reflects the last update time.

Monday, February 3, 2014

Merging pdf files

This post is about combining pdf files. It complements 2 earlier posts on splitting pdf files - part 1, and 2.

I am using a tool named SimpleScan to scan in multiples pages of a document. Each page is scanned into a separate pdf file. I must find a way to stitch the pdf files together into one single pdf.

You can use either the pdftk command, or the gs command to merge pdf files. You may recall that they are the same commands you would use to split pdf files. In the examples below, the input files are T4a.pdf, T4b.pdf, and T4c.pdf; the merged output file is combined.pdf.

  • pdftk
    $ pdftk T4a.pdf T4b.pdf T4c.pdf output combined.pdf
    
  • gs (GhostScript)
    $ gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -sOutputFile=combined.pdf T4a.pdf T4b.pdf T4c.pdf 
    GPL Ghostscript 9.05 (2012-02-08)
    Copyright (C) 2010 Artifex Software, Inc.  All rights reserved.
    This software comes with NO WARRANTY: see the file PUBLIC for details.
    Processing pages 1 through 4.
    Page 1
    Loading NimbusSanL-Regu font from /usr/share/fonts/type1/gsfonts/n019003l.pfb... 4247256 2644865 2257128 952885 3 done.
    Loading NimbusSanL-Bold font from /usr/share/fonts/type1/gsfonts/n019004l.pfb... 4288248 2754288 2277312 983470 3 done.
    Loading NimbusMonL-Regu font from /usr/share/fonts/type1/gsfonts/n022003l.pfb... 4331192 2899511 2438784 1137910 3 done.
    Page 2
    Loading NimbusSanL-BoldItal font from /usr/share/fonts/type1/gsfonts/n019024l.pfb... 4370920 2866410 2479152 934054 3 done.
    Loading NimbusSanL-ReguItal font from /usr/share/fonts/type1/gsfonts/n019023l.pfb... 4410584 2982313 2499336 1004810 3 done.
    Page 3
    Page 4
    Processing pages 1 through 4.
    Page 1
    Page 2
    Page 3
    Page 4
    Processing pages 1 through 4.
    Page 1
    Page 2
    Page 3
    Page 4
    

P.S. You can also merge pdf files using ImageMagick. Refer to my post.

Wednesday, January 29, 2014

How to split up PDF files - part 2

In an earlier post, I used the pdftk tool to extract pages from a pdf file. I had no reason to investigate alternative solutions until I encountered the following problem.

I had to extract the first 4 pages of a pdf document. The normally reliable pdftk command generated a Java exception.

$ pdftk T4.pdf cat 1-4  output outputT4.pdf
Unhandled Java Exception:
Unhandled Java Exception:
java.lang.NullPointerException
   at gnu.gcj.runtime.NameFinder.lookup(libgcj.so.12)
   at java.lang.Throwable.getStackTrace(libgcj.so.12)
   at java.lang.Throwable.stackTraceString(libgcj.so.12)
   at java.lang.Throwable.printStackTrace(libgcj.so.12)
   at java.lang.Throwable.printStackTrace(libgcj.so.12)

To troubleshoot the problem, I executed the pdftk command using a different input pdf file. It worked just fine. The problem appears to be the specific input pdf file.

At that point, I started looking for an alternative tool.

gs, aka Ghostscript, is a previewer for PDF as well as PostScript files.

You can direct gs output to various output devices using the -sDEVICE parameter. The pdfwrite device specifies that the output will be in PDF file format.

The page range to extract is defined by -dFirstPage and -dLastPage parameters. The name of the output file is specified using -sOutputFile parameter.

$ gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dFirstPage=1 
-dLastPage=4 -sOutputFile=outputT4.pdf T4.pdf
GPL Ghostscript 9.05 (2012-02-08)
Copyright (C) 2010 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
**** Warning: considering '0000000000 XXXXX n' as a free entry.
**** Warning: considering '0000000000 XXXXX n' as a free entry.
**** Warning: considering '0000000000 XXXXX n' as a free entry.
Processing pages 1 through 4.
Page 1
Loading NimbusSanL-Regu font from /usr/share/fonts/type1/gsfonts/n019003l.pfb... 4287624 2669241 2475832 1154775 3 done.
Loading NimbusSanL-Bold font from /usr/share/fonts/type1/gsfonts/n019004l.pfb... 4328616 2778664 2516200 1192102 3 done.
Loading NimbusMonL-Regu font from /usr/share/fonts/type1/gsfonts/n022003l.pfb... 4371912 2946486 2677672 1350807 3 done.
Page 2
Loading NimbusSanL-BoldItal font from /usr/share/fonts/type1/gsfonts/n019024l.pfb... 4431472 2877228 2738224 1120988 3 done.
Loading NimbusSanL-ReguItal font from /usr/share/fonts/type1/gsfonts/n019023l.pfb... 4471488 2998784 2758408 1209901 3 done.
Page 3
Page 4
**** This file had errors that were repaired or ignored.
**** The file was produced by: 
**** >>>> iText 1.4.5 (by lowagie.com) <<<<
**** Please notify the author of the software that produced this
**** file that it does not conform to Adobe's published PDF
**** specification.

The above output messages provided a clue on why the input pdf file was problematic. The pdf file does not "conform to Adobe's published PDF specification." To its credit, gs "repaired or ignored" the problem. It continued on to successfully extract the pages. In this particular example, gs is more error tolerant than its counterpart, pdftk.

P.S. You can also use ImageMagick to divide pdf files. See my post.

Wednesday, January 22, 2014

Print text files with multiples pages per sheet

a2ps is the venerable tool for formatting text files for Postscript printers. This post focuses on how to call a2ps to print multiple pages per sheet.

To install a2ps and gv aka ghostview, which a2ps uses to preview output files:

$ sudo apt-get install a2ps
$ sudo apt-get install gv

Layout

You can layout a sheet of paper into rows and columns of pages.

To print the emacs config file in the above format, any of the following will do:

$ a2ps ~/.emacs
$ a2ps --rows 1 --columns 2 ~/.emacs
$ a2ps -2 ~/.emacs

Note that with no explicit instruction, the default layout is 1x2 in the landscape orientation.

a2ps provides shortcuts to specify the number of rows and columns for common configurations. For example, -2 is equivalent to 1 row and 2 columns. Valid shortcuts are -1 to -9.

Paper size

North American a2ps users need to modify the output paper size. a2ps was written in Europe, and uses A4 as the default paper size. North America uses a different standard, and a common paper size is called Letter - 8.5 x 11 inches. Printing A4 on Letter-sized paper results in text being cropped at the end of each line in the right column.

To modify the paper size to Letter:

$ a2ps -M Letter .emacs

Instead of overriding the paper size in every single run, you can change the default locally (per user) or globally (system-wide). To specify the paper size for a user, add the following line to $HOME/.a2ps/a2psrc.

Options: --medium=Letter

To change the default system-wide, edit the file /etc/a2ps-site.cfg. Look for the Options: --medium line and change the value to Letter.

Preview of output

By default, a2ps sends the output to the printer. Sometimes you want to override that behavior in order to preview the output. You may redirect the output to a PostScript file or directly to ghostview.

To create a PostScript output file, and open it using ghostview:

$ a2ps -o temp.ps -M Letter .emacs
[.emacs (plain): 31 pages on 16 sheets]
[Total: 31 pages on 16 sheets] saved into the file `temp.ps'
[101 lines wrapped]
$ gv temp.ps

a2ps provides a shortcut to preview its output directly in ghostview.

$ a2ps -P display -M Letter .emacs

The -P parameter normally specifies the printer name. However, display is a special name to redirect output to ghostview.

Multiple files

a2ps also supports multiple input files. By default, each file begins printing on a new sheet ("file alignment"). Empty cells in the layout are not filled. For example, given 2 input files - 1.txt and 2.txt - that are each 1 page long, each file will be printed on a separate sheet, leaving the sheets half empty.

You can control the file alignment using -A parameter. If file alignment is fill, a2ps prints a file beginning in the next available cell, leaving no empty cell in between it and the previous file.

$ a2ps -A fill  1.txt 2.txt
[1.txt (plain): 1 page on 1 sheet]
[2.txt (plain): 1 page on 1 sheet]
request id is ML-1640-Series-162 (0 file(s))
[Total: 2 pages on 1 sheet] sent to the default printer

a2ps has too many useful features to be covered in a single post. Read the man page if you want to print double-sided, or you want to number each line in the output.