結城浩のはてなブログ

ふと思いついたことをパタパタと書いてます。

自炊した本をコマンドラインから手軽に開くための簡単なPerlスクリプト(findbook.pl)

コンテキスト

  • たくさん本を自炊したので手元に数百のPDFファイルがある。
  • Windows 7

問題

  • コマンドラインから目的の本を開きたい。
  • 書名や著者名の一部しか覚えていない。
  • 目視で探すのは苦痛。
  • ファイル名を見せられれば、それが目的の本かどうかは分かる。

解決

  • 簡単なPerlスクリプト(findbook.pl)を作り、pl2bat findbook.pl でバッチファイルを作った。
  • コマンドラインから書名や著者名の一部を入力すると、マッチするファイルの一覧を番号付きで表示する。
  • 続けて番号を入力すれば、そのPDFファイルを開く。

実行例

> findbook オイラー
1. なっとくするオイラーとフェルマー(小林昭七).pdf
2. オイラー、リーマン、ラマヌジャン(黒川信重).pdf
3. オイラーその生涯と業績.pdf
4. オイラーに学ぶ.pdf
5. オイラーの贈物.pdf
6. オイラー探検.pdf
7. 無限オイラー解析(高橋浩樹).pdf
Which book?5
(ここで"オイラーの贈物.pdf"が開かれる)

> findbook フェルマー サイモン
1. フェルマーの最終定理(サイモン・シン).pdf
Which book?1
(ここで"フェルマーの最終定理(サイモン・シン).pdf"が開かれる)

スクリプト(findbook.pl)

use strict;
use warnings;
no warnings 'numeric';

use Encode;
use URI::Escape;

my $bookdir = q{c:/Users/yourname/yourbookdir};

if (@ARGV == 0) {
    print "Usage: findbook any-part-of-book-name\n";
    print "Examle: findbook Perl\n";
    exit;
}

my @query = @ARGV;
for my $q (@query) {
    $q = URI::Escape::uri_escape($q);
}

my @found;

chdir("$bookdir");

PDF:
for my $name (glob("*.pdf")) {
    for my $q (@query) {
        unless (URI::Escape::uri_escape($name) =~ /$q/i) {
            next PDF;
        }
    }
    push(@found, $name);
}

my $index = 0;
while ($index < @found) {
    printf("%-2d.%s\n", $index + 1, $found[$index]);
    $index++;
}

my $selected = 0;
print "Which book? ";
$selected = <STDIN>;

if ($selected > 0) {
    my $exec = sprintf(qq{start "" "%s"}, $found[$selected - 1]);
    system($exec);
}
  • 注:uri_escapeをしているのは正規表現エスケープをどうすればいいか忘れたから…(><)