Terminalの設定で気になることがあり、連載のバックナンバーを漁っていたところ、かつてのTerminalではマルチバイト文字が通らなかったなあ(リンク)……などといまさらながら改良 -- NEXTSTEPの頃は普通にできていたのだから進化ではない -- の足跡に感じ入ってしまった。

しかし、macOSのマルチバイト対応はいまだ道半ば。対応できていない、というかするつもりがないコマンドのなんと多いことよ。デフォルトシェルがtcshからbash(およびGNU readline)に変更されたことに伴い、シェルで日本語の表示と入力はどうにか処理できるようになり、lessなど一部のコマンドもUTF-8エンコードのテキストならば表示できるようになったが、あの問題というか"仕様"はそのままだ。

それは「濁点の扱い」。HFS+では、濁点・半濁点やウムラウトなどの補助記号を文字本体と分離して符合化する「NFD(Normalization Form Canonical Decompression)」と呼ばれる正規化形式を採用している。一方、WindowsやLinuxなど他の多くのOS(のファイルシステム)では、補助記号の有無にかかわらず1文字は1文字として扱う「NFC(Normalization Form Canonical Compression)」を採用している。

Terminalでlsコマンドを実行し、ファイル名を表示したところでこの問題には気付かないが、findコマンドを実行すればわかる。第169回で詳しく解説しているので、なぜこうなるかはそちらを参照してほしい。

名前に「ポ」を含むファイルが、「ホ」と「ポ」の両方でヒットしていることがわかる

この問題への対策として、第169回ではiconvコマンドで文字列をNFDに変換するというクイックハックを紹介したが、日本語IMEの出力がNFCである以上、どうにもならない部分がある。

たとえば、Terminalでカレントディレクトリ上に「スキ.pdf」と「スギ.pdf」があるとき、「スキ」まで入力して(bashの)入力補完機能を使えば「スキ.pdf」だけが表示されそうなものだが、HFS+上で「ギ」は「キ゛」として符合化されているため、「スキ.pdf」と「スギ.pdf」の両方がヒットしてしまう。この仕様については、GNU readline(bashの入力を司るライブラリ)レベルでの対応が必要だ。

シェル(bash)の入力補完機能も、NFDを考慮していない

一方、日本語の扱いを巡る問題はgrepにもつきまとう。macOS Sierraに収録のgrepはBSD版(v2.5.1-FreeBSD)であり、文字コードをUTF-8に変換しないかぎり日本語で全文検索できないため、iconvコマンドを組み合わせるなど工夫しなければならない。

だから、濁点・半濁点を含むファイル名を考慮しつつ、TerminalからシフトJISのテキストを全文検索するとなると、かなり面倒なことになる。第169回で紹介したスキームをそのままなぞるとすれば、次のようなコマンドラインになるだろうか。かなりゲッソリする感じだ。

$ find . -name `echo "ぷくぷく.txt" | iconv -f UTF8 -t UTF8-MAC` -print | xargs iconv -f CP932 -t UTF8 | grep "キーワード"

MacにはSpotlightがあるじゃないか、だからそもそもファイル名を気にする必要はなく、テキストファイルの文字コードもシフトJISなら問題なし、という割り切りもできるだろうが、Terminalでの作業比率が高い筆者としてはそうもいかない。それに、USBメモリなど外部ストレージはSpotlightのデータベース化対象外としたい事情もあり、必要なときgrepを実行するほうがいい。

そこで巡り会ったツールが「Gren」。RubyGemの形で公開されているため、インストールはコマンドライン1行でOK。HomeBrewなどのパッケージ管理システムを必要としないので、システムを可能なかぎりシンプルに保ちたい向きにはいいチョイスだ。

$ sudo gem install gren

RubyGemなのでパッケージ管理システムは不要、コマンドライン1行でインストールは完了する

この「Gren」、なかなか使い勝手がいい。引数がすべて小文字のときは大文字/小文字の区別をせず、大文字混じりのときは厳密に区別する(厳密に小文字を検索するオプションもある)、という融通の効く仕様もうれしい。ファイル名/ディレクトリ名での絞り込み、AND検索やOR検索といった機能も用意されている。もちろん、肝心な文字コード自動判定機能付きなので、UTF-8やシフトJISなど複数のエンコード形式が混在する領域での全文検索にも役に立つ。

ほかにも「LV」に付属の「lgrep」を使う、UNIX系OS定番の文字コード変換ツール「nkf」を使うなどの方法がある。いずれにせよ、濁点・半濁点が含まれるファイル/ディレクトリをTerminalで検索対象とするのはかなり面倒だが、全文検索ツールを使いやすくしてファイル/ディレクトリ名の入力を省くことが、ひとつの現実的な対策なのかもしれない。

日本語で全文検索できるようにすることが、濁点・半濁点を含むファイル名の扱いに対する1つの答えなのかもしれない