Skip to content

Instantly share code, notes, and snippets.

@2sin18
Created November 24, 2013 14:57
Show Gist options
  • Save 2sin18/7628127 to your computer and use it in GitHub Desktop.
Save 2sin18/7628127 to your computer and use it in GitHub Desktop.
Sync information between BibTeX file and PDF XMP
#!/usr/bin/perl -w
# Sync the information between BibTeX and PDF XMP.
# sam.yuen@foxmail.com
use strict;
use warnings;
use POSIX;
use Getopt::Std;
use File::Basename;
use File::Find;
use File::Spec;
use Text::BibTeX;
use PDF::API2;
$|++;
my $pwd = getcwd();
my %options; getopts('f:', \%options);
my $attachment = $options{'f'} || 'file';
my $bibpath = shift || '$pwd/documents.bib';
$bibpath = File::Spec->rel2abs($bibpath) if !File::Spec->file_name_is_absolute($bibpath);
my $bibdir = dirname($bibpath);
chdir($bibdir);
if (-e $bibpath) {
my $bibfile = Text::BibTeX::File->new($bibpath);
while (my $entry = new Text::BibTeX::Entry $bibfile) {
next unless $entry->parse_ok && $entry->metatype == BTE_REGULAR;
if ($entry->exists($attachment)) {
my $path = $entry->get($attachment);
next if (!defined $path || $path !~ m/:application\/pdf$/);
$path =~ s/:application\/pdf$//g;
$path =~ s/^.*://;
$path = File::Spec->rel2abs($bibdir."/".$path)
if !File::Spec->file_name_is_absolute($path);
next if (!-e $path);
print "$path is not processed correctly.\n"
if !eval {
my $file = PDF::API2->open($path);
my %xmp = $file->info();
my $title = $entry->get('title');
$xmp{'Title'} = $title if defined $title;
my $author = $entry->get('author');
$xmp{'Author'} = $author if defined $author;
my $keywords = $entry->get('keywords');
$xmp{'Keywords'} = $keywords if defined $keywords;
my $subject = $entry->print_s;
$xmp{'Subject'} = "BibTeX:".$subject if defined $subject;
$file->info(%xmp);
$file->update();
print "bibtex xmp is added to $path\n";
};
}
}
$bibfile->close;
}
else {
my @pdfpaths;
find(sub {
my $path = $File::Find::name;
return if -d $path || $path !~ m/\.pdf$/;
push @pdfpaths, $path;
}, $bibdir);
my $pdfpath_count = @pdfpaths;
return if $pdfpath_count == 0;
open BFH, ">", $bibpath or die $!;
foreach my $path (@pdfpaths) {
print "$path is not processed correctly.\n"
if !eval {
my $file = PDF::API2->open($path);
my %xmp = $file->info();
my $subject = $xmp{"Subject"};
if ($subject =~ m/^BibTeX:/) {
$subject =~ s/^BibTeX://;
printf BFH $subject;
}
};
}
close BFH;
}
@2sin18
Copy link
Author

2sin18 commented Jul 20, 2014

  • Use bibpdf.pl /path/to/docs.bib to sync information from the .bib file to PDFs.
  • Use bibpdf.pl to sync information from PDFs in current directory to a .bib file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment