#!/usr/bin/env ruby # This script is a front-end to pdftk. With no options, it # displays the metadata for the specified PDF files. Or you # can use the -a, -t, and -k options to change the # Author, Title, and Keywords metadata fields. $VERBOSE = true require 'getoptlong' $author = nil $title = nil $do_backup = false $display = true $strip_xmp = false $keywords = nil def usage puts "usage: metadata [-a \"author\"] [-t \"title\"] [-k \"keywords\"] [-b] [-x] pdffile" puts " -a set author" puts " -t set title" puts " -k set keywords" puts " -b make backup file" puts " -x strip XMP metadata" exit 1 end def parse_args opts = GetoptLong.new( [ '-a', '--author', GetoptLong::REQUIRED_ARGUMENT ], [ '-t', '--title', GetoptLong::REQUIRED_ARGUMENT ], [ '-k', '--keywords', GetoptLong::REQUIRED_ARGUMENT ], [ '-b', '--backup', GetoptLong::NO_ARGUMENT ], [ '-x', '--xmp', GetoptLong::NO_ARGUMENT ] ) opts.each do |opt, arg| case opt when '-a' $author = arg $display = false when '-t' $title = arg $display = false when '-k' $keywords = arg $display = false when '-b' $do_backup = true when '-x' $strip_xmp = true $display = false end end end def display_metadata(pdf) key = nil puts "#{pdf}:" IO.popen("pdftk #{pdf} dump_data", "r") do |pipe| pipe.each do |line| line.chomp if line =~ /^InfoKey: (.*)$/ key = $1 elsif line =~ /^InfoValue: (.*)$/ printf(" %-16s %s\n", key, $1) end end end end def change_metadata(old, new) puts "Updating metadata" IO.popen("pdftk #{old} update_info - output #{new}", "w") do |pipe| if $author pipe.puts("InfoKey: Author") pipe.puts("InfoValue: #{$author}") end if $title pipe.puts "InfoKey: Title" pipe.puts "InfoValue: #{$title}" end if $keywords pipe.puts "InfoKey: Keywords" pipe.puts "InfoValue: #{$keywords}" end end end def copy_without_xmp(old, new) puts "Stripping XMP metadata" system("pdftk #{old} cat output #{new}\n") end def make_backup(pdf) if $do_backup backup = "#{pdf}.bak" File.delete(backup) if File.exist?(backup) File.rename(pdf, backup) puts "#{pdf} modified, original in #{backup}" else File.delete(pdf) puts "#{pdf} modified, no backup made" end end def process_files if ARGV.length == 0 puts "no pdf files specified" usage end ARGV.each do |pdf| if $display display_metadata(pdf) else # Modify metadata. newfile = "#{pdf}.new" newfile2 = "#{pdf}.new2" if File.exist?(newfile) puts "#{newfile} already exists, won't overwrite" else if $strip_xmp copy_without_xmp(pdf, newfile2) change_metadata(newfile2, newfile) if File.exist?(newfile2) File.delete(newfile2) end else change_metadata(pdf, newfile) end if File.exist?(newfile) make_backup(pdf) File.rename(newfile, pdf) else puts "An error occured; #{pdf} is unchanged" end end end end end def main parse_args process_files end main