2019年08月16日

mimeopen コマンドのフォールバックアプリを設定する

xdg-open にファイルを渡すと時々とんちんかんなアプリが開くことがあって困っていた。例えば .js は VLC、 .rb は Calibre の電子書籍ビューアなど。

解決法

mimeopen コマンドが原因。 application/octet-streamtext/plain になにかしらアプリケーションを関連付ければ、すべてのケースを拾える。 octet-stream は迷ったが、とりあえずブラウザに渡してみればよしなにやるだろうと思って設定してみた。

# ~/.config/mimeapps.list
[Default Applications]
text/plain=featherpad.desktop;
application/octet-stream=firefox.desktop;

.js だけやっぱりブラウザで開かれるけど、バイナリデータが来るかもしれないことを考えるとテキストエディタじゃいまいちなので我慢する。

詳解

xdg-open の中身

Lubuntu 18.10 以降では xdg-openmimeopen -L -n を最終的に呼ぶので試してみる。

$ mimeopen foo.rb
Please choose a default application for files of type application/x-ruby

  1) E-book Viewer  (calibre-ebook-viewer)
  2) calibre  (calibre-gui)
  3) LibreOffice Writer  (libreoffice-writer)
  4) FeatherPad  (featherpad)
  5) Vim  (vim)
  6) Other...

この状態で xdg-open を実行すると1行目の Calibre の書籍ビューアが立ち上がる。そしてCalibreはスクリプトを開けずエラーが出る。不毛だと思いながら閉じる。

.rb に直接関連付けられたアプリがないようだ。しかしテキストが開けそうなアプリ一覧が来てるが、ここはビューワよりテキストエディタが一番に来てほしい。

mimeopen の中身

mimeopen の Perl ライブラリ(File::MimeInfo) の説明によると mimeopen はファイルの MIME タイプに関連付けられたアプリがないときには「祖先」をたどって調べていくらしい。しかし mimeopen -D (debug オプション) を付けたとしても何が祖先かは出てこない。コードを読んでやっとわかった。

  1. MIME タイプによっては祖先があらかじめ設定されている
  2. トップレベルタイプが text (= text/ で始まる) 場合は text/plain を、
  3. それも含めすべてのタイプは application/octet-stream を祖先として持つ

そういうわけで application/octet-stream になんか設定しておけば、未知の MIME タイプであってもそれが起動する。

なんで手元の環境で application/octet-stream が VLC で text/plain の上位2件が Calibre なのかは面倒になったので調べない。

MIME タイプの継承

せっかくなので MIME の祖先を見てみる。Perl 初めて書いた。
関数名の isa は謎。引数が2個来ると親子かどうかの真偽値を返すようだから、ruby の is_a?、Python の isinstance 的な?

#!/usr/bin/perl
use File::MimeInfo qw/mimetype_isa/;

my $type = $ARGV[0];
for my $t (mimetype_isa($type)) {
  print($t, "\n");
}

javascript は text/plain じゃない。(伏線回収)

$ perl ancestor.pl application/javascript
application/ecmascript
application/octet-stream
$ perl ancestor.pl application/x-perl
application/x-executable
text/plain
application/octet-stream
$ perl ancestor.pl application/x-ruby
application/x-executable
text/plain
application/octet-stream

OpenDocument はオフィス文書の形式だが、中身は XML を ZIP で固めたものなので祖先に application/zip が入っている(上記の(1)に該当)。

$ perl ancestor.pl application/vnd.oasis.opendocument.spreadsheet
application/zip
application/octet-stream

Markdown。 text/plain が2回出てるのは(1)と(2)が重複してるものか。

$ perl ancestor.pl $(mimetype -b foo.md) # text/markdown
text/plain
text/plain
application/octet-stream

ライセンスファイルも。mimetype の話になるがこのあたりはファイル名で判断してるので mimetype -M (拡張子を無視)とするとただの text/plain になる。

$ perl ancestor.pl $(mimetype -b COPYING) # text/x-copying
text/plain
text/plain
application/octet-stream

というのが StackExchange に投稿したもののいい回答がつかず、9ヶ月越しに自己解決した質問だったのである How can I set default application for unknown file on xdg-open / mimeopen?

posted by かぷらす at 19:29| Comment(0) | 作業記録 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください