改行コードの変換と上書きモードについて。あるいは iconv と nkf に見る思想の違い

文字コード変換、再び


前エントリid:CCG さんからコメントにてご指摘がありましたので、その点について補足のエントリを書きます。完全に続きの話なので、未読の方は、まず前エントリをご参照下さい。

改行コードの変換

文字コードを変換する場合は、同時に改行コードも変換したくなる事が多いかと思いますし、実際、 nkf ではそういった変換をサポートしていましたが、 iconv には改行コードの変換機能はありません。

したがって、改行コードを変換したい場合には別のコマンドを併用する必要があります。改行コードの変換は、 tr や sed で力技で片付けるのも手です*1が、 dos2unix とか unix2dos といった簡便なコマンドもあります。

$ iconv -f SHIFT-JIS -t UTF-8 README.TXT | dos2unix > readme.txt.utf8
(文字コードが Shift JIS 、改行コードが CR+LF の README.TXT を、
  文字コードを UTF-8、改行コードを LF に変換して readme.txt.utf8
  として保存する。)

オプションも幾つかありますが、詳細は manpage を見てください。

上書きモード

さて、もう一点のツッコミ、「上書きモード」についてですが、この機能もiconvにはありません*2

なので、変換後の結果を変換元のファイルに上書きしたい場合、古いバージョンのnkfでやっていたように、いったん別ファイルに書くなどした後 mv するしかありません。頻繁に必要になる機能なら、nkf互換なスクリプトを書いてしまったほうが良いことになって、なんだか本末転倒な感じですね。

この点は nkf が残り続ける最大の原因なのかもしれません。

iconv と nkf の思想の違い

「なんで iconv コマンドには、こんな大事な機能が含まれていないのか」と、疑問に感じる方も多いと思います。その理由を端的にぶっちゃけて言えば「geek受けが悪いから」、言いかえるなら「それはPOSIX的では無いから」ということになります。

POSIXの思想では、各コマンドは単機能であるべきで、1つのデータに複数の処理を施したい場合は、パイプで繋げば良い、ということになっています。そのため、文字コードの変換と、改行コードの変換は別コマンドになっている方が「美しい」のです。多数のコマンドを標準入出力で繋ぐスタイルにしてしまうと、「上書きモード」を実現できなくなりますが、それはしかたのないことです。いやならシェルのリダイレクトの機能を拡張してみるのはどうでしょう。それなら「美しい」設計になりそうですよ。なに? タイムスタンプも保持したい? それはけしからん。内容が変換されているのだからタイムタンプは変わって然るべきだ。どうしてもやりたいなら touch コマンドで実現出来るが、君の書いたそのスクリプトは世には出さないようにしてくれたまえ。


……うん。書いててちょっと気持悪かった。

まぁ、geekはそんな思考の持ち主なので、iconv自体にこれらの機能が追加されることは無さそうです。逆に nkf は「良く使うんだから一緒になってたほーが便利でしょ。というか、パイプとかよくわかんないし。」といったDOS由来の思想が見え隠れするような気がします。

私の場合

「思想なんてどうでもいいよ。必要で面倒なパーツが揃っていて、ちゃんとメンテナンスされてるなら、あとは自分でなんとかするから。」というのが私の基本スタンスです。あれば使うし、無ければありもので何とかする。ありもので工夫するのもそれはそれで楽しいしね。根っこにあるのは日曜プログラマなので。

あと、私が使うのは、ほんんどこの形

$ iconv -f SHIFT-JIS -t UTF-8 README.TXT | less
$ iconv -f SHIFT-JIS README.TXT | less
(2008-09-27修正: -t のデフォルトは端末のロケールなので、lessで見るのなら省略可能です。)

なので、改行コード変換も上書きモードも普段は要らない、というのも大きいかもしれません。*3

そういうわけなので、nkfよりもiconvの方を薦める、というのも、機能の違いでも思想の違いでもなくて、単純に継続メンテの可能性だけなんです。5年後にiconvが無くなっていることは無いような気がしますが、nkfはもしかしたら化石となっているかもしれない、と。まぁ、実際にはどちらも確実に生き残ってるでしょうけどね。

*1:というか、私はsedの方が手に馴染んでますw

*2:dos2unixにはOld file mode という名で、同機能のオプションがあるのですが……

*3:だから前エントリでは、すっかり失念していたのですね