Tikaを使って指定したディレクトリ以下の全ファイルのメタデータを収集

会社で外部に公開しているPDFファイルの作成者やタイトルにおかしいもの(社名が間違っている etc.)があることに気づき、 会社のファイルサーバにあるWord、Excel、PowerPoint、PDFファイルのメタ情報を一覧で出力し、 Excelにインポートして変なメタ情報が設定されていないかチェックするためのスクリプトを作ってみた。

準備

まずはapacheからTikaをダウンロード(執筆時点では1.11が最新)

wget http://ftp.jaist.ac.jp/pub/apache/tika/tika-app-1.11.jar

全メタデータを収集

とにかく全部のメタデータを収集したいときは、tikaのjarファイルと同じディレクトリに以下のようなスクリプトを配置。 検索対象のディレクトリは3行目で指定する。

#!/bin/bash

dir=~/Documents/
output=metadata.xml
port=12345
tmpfile=temp.txt

java -jar tika-app-1.11.jar -s -x --port $port > $tmpfile &
procid=$!
sleep 1

echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" > $output
echo "<files>" >> $output
find "$dir" -iname "*.pdf" -o -iname "*.doc" -o -iname "*.doc?" -o -iname "*.xls" -o -iname "*.xls?" -o -iname "*.ppt" -o -iname "*.ppt?" | while read i
do
  echo "<file>" >> $output
  echo " <filepath><![CDATA[$i]]></filepath>" >> $output
  cat "$i" | nc 127.0.0.1 $port > $tmpfile
  cat "$tmpfile" | grep -E "^<meta " >> $output
  echo "</file>" >> $output
done
echo "</files>" >> $output

kill $procid

これに実行権限をつけて実行すると、同じディレクトリにmetadata.xmlというXMLファイルが生成される。

すると、metadata.xmlが

<?xml version="1.0" encoding="utf-8" ?>
<files>
<file>
 <filepath><![CDATA[/home/***/Documents/*************.pdf]]></filepath>
<meta name="pdf:PDFVersion" content="1.5"/>
<meta name="xmp:CreatorTool" content="****"/>
<meta name="Keywords" content="キーワード"/>
<meta name="access_permission:modify_annotations" content="true"/>
<meta name="access_permission:can_print_degraded" content="true"/>
</file>
</files>

という出力になり、すべてのメタデータを収集できる。

また、いちいちJVMを起動すると遅いので、サーバモードでTikaを起動し(起動するまで時間がかかるので念の為1秒待機)、最後にプロセスをkillしている。 (Apache Tikaのサーバモードの良い終了のさせ方が分からなかった)

必要なメタデータだけを収集

なお、すべてのメタデータを収集するとおもすぎるので、 必要なメタデータだけを収集するようなスクリプトも書いてみた(“creator"と"title"だけを抜き出す)。

違いは、オプションを-xから-mに変えて、プレーンテキストでメタデータを吐かせて処理している。

#!/bin/bash

dir=~/Documents/
output=metadata.xml
port=12345
tmpfile=temp.txt

java -jar tika-app-1.11.jar -s -m --port $port > $tmpfile &
procid=$!
sleep 1

echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" > $output
echo "<files>" >> $output
find "$dir" -iname "*.pdf" -o -iname "*.doc" -o -iname "*.doc?" -o -iname "*.xls" -o -iname "*.xls?" -o -iname "*.ppt" -o -iname "*.ppt?" | while read i
do
  echo "<file>" >> $output
  echo " <filepath><![CDATA[$i]]></filepath>" >> $output
  cat "$i" | nc 127.0.0.1 $port > $tmpfile
  for j in "creator" "title"
  do
    echo -n " <$j><![CDATA[" >> $output
    cat "$tmpfile" | perl -ne "print if s|^$j: (.+)\n$|\\1|" >> $output
    echo "]]></$j>" >> $output
  done
  echo "</file>" >> $output
done
echo "</files>" >> $output

kill $procid

手抜き実装のため、“dc:creator"などを指定すると、XMLとしてはInvalidになってしまうので注意(dcが名前空間扱いになってしまう)。

この場合は、出力結果として、

<?xml version="1.0" encoding="utf-8" ?>
<files>
<file>
 <filepath><![CDATA[/home/***/Documents/**********************.pdf]]></filepath>
 <creator><![CDATA[作成者名]]></creator>
 <title><![CDATA[テストタイトル]]></title>
</file>
<file>
 <filepath><![CDATA[/home/***/Documents/**********************.pdf]]></filepath>
 <creator><![CDATA[作成者名]]></creator>
 <title><![CDATA[テストタイトル]]></title>
</file>
</files>

という感じのXMLファイルが生成されるので、あとは煮るなり焼くなり。 この形式だとExcelでXMLをインポートするのも楽。 ただし、改行が入っているメタデータは1行目だけになる。