Greple で iCal データを検索する

追記: 申し訳ありませんが、--print で使用する関数の仕様を変更して、関数の返り値を出力するようにしました。 関数内で出力している場合は、空文字列を返すようにしてください。


--chdir, --glob オプション

OS X のカレンダーコマンドは iCalendar という形式でデータを管理していて、ファイルは ~/Library/Calendars というディレクトリの下に保存されている。

たとえば、こんな風にすれば iCal のデータを検索することはできる。

% cd ~/Library/Calendars
% grep PATTERN *.caldav/*.calendar/Events/*.ics

Greple--chdir--glob オプションを使うと、同じことがこんな風にできる。

% greple --chdir ~/Library/Calendars  --glob='*.caldav/*.calendar/Events/*.ics' PATTERN

複数のディレクトリを --chdir で指定することもできる。 その場合、それぞれのディレクトリに移動した後で --glob オプションを解釈する。

% greple --chdir '~/Library/Calendars/*.caldav/*.calendar/Events/' --glob '*.ics' PATTERN

憶えておくのは大変なので、alias を作ってもいいし、~/.greplerc ファイルに次のように書いておくと --ical_data という新しいオプションが有効になる。

% greple --ical_data PATTERN

これだと、マッチした行しか表示されないので日付とかがわからない。 iCal のデータは、1つのイベントを1つのファイルに保存しているので、ファイル全体を表示させるためには、--all というオプションを使う。

% greple --ical_data --all PATTERN

ここまでは grep-r オプションを使っても、大体同じことができる。 マニュアルには書いてないが、-C オプションに -1 を指定するとファイル全体を表示するようだ。 と思ったけど、-C オプションに負の数を指定した場合の挙動は不可解だ。

% grep -rhC-1 --include '*.ics' PATTERN *.caldav

--print オプション

greple--print オプションを使うと、出力用の関数を定義することができる。 もっとも簡単な使い方はこんな具合。

% greple --print='sub{$_}' PATTERN

値には Perl のサブルーチン名を指定するか、直接コーディングする。 マッチした領域は $_ 変数に入ってきて、関数の返り値が出力される。

iCal のデータを表示するためには、たとえば ~/.greplerc にこのような関数を定義する。

.greplrc definition to search iCal data and displa ...

こうして、次のように実行すると、iCal のデータを1行ずつ表示してくれる。 イベント名だけを検索したければ SUMMARY 行を指定する。 TODO などを除外して EVENT だけを検索したければ、VEVENT というフィールドも指定する。

% greple --ical PATTERN

% greple --ical '^SUMMARY.*PATTERN'

% greple --ical 'VEVENT ^SUMMARY.*PATTERN'

これだと、順番が出鱈目なので、日付順に表示したければ結果を sort する。 --of オプションで出力フィルタを指定することができるので、.greplerc の中に --of=sort を入れてしまっても構わない。 試しに、10年前の正月にどんな映画を観ていたかを検索してみるとこんな結果になった。 なるほど、とっとこハム太郎を観ていたのかw

% greple --ical '200401\d\d 映画' | sort
2003/01/02 14:00-15:00 映画:とっとこハム太郎 ハムハムハムージャ!幻のプリンセス
2003/01/02 15:00-16:30 映画:ゴジラ対メカゴジラ
2004/01/02 12:20-13:25 映画:劇場版 とっとこハム太郎ハムハムグランプリオーロラ谷の奇跡リボンちゃん危機一髪
2004/01/02 13:30-15:00 映画:ゴジラ×モスラ×メカゴジラ 東京SOS
2004/01/08 19:30-21:30 映画:ミシェル・ヴァイヨン@池袋HUMAX
2004/01/13 20:10-22:00 映画:ブルース・オールマイティ@サンシャイン
2004/01/16 20:40-22:55 映画:半落ち@サンシャイン
2004/01/21 22:00-00:00 映画:リクルート
2004/01/24 21:30-23:30 映画:タイムライン
2004/01/25 21:00-23:00 映画:首都消失@TV
2004/01/29 20:30-23:00 映画:ミスティック・リバー@新宿ジョイシネマ

おや、2003年のデータが混じってるな?と思ったら、こうやって中身を見ることができる。

% greple --ical_data --all ハムハムハムージャ!

すると、DTSTAMP というフィールドが2004年になっていることがわかった。 RFC2445 によれば、これはオブジェクトが作成された日付ということだ。

厳密に書くとすればこんな具合だろうか。 最初からきっちり書くのではなく、ゆるく初めて必要に応じて絞り込むような使い方がお勧めである。

% greple --ical '^BEGIN:VEVENT ^DTSTART.*200401\d\d ^SUMMARY.*映画' | sort