2007年3月29日木曜日

convmvで、日本語のファイル名の文字コードを変換するときに、一度テスト実行してみる

以前に、convmvというツール(FreeBSDではports/converters/convmvにある)を使うと、ファイル名の文字コード変換ができることを知って・・・



やってみたら、おかしくなってしまいましたとさ・・・とか書いたんですが、あれって、実は、別にconvmvにはおかしいことはなくて、Windows 2000 Serverがおかしかったのでした。Apache 2.2.xのWebDAVを使って、Windows 2000にて日本語のファイル名で作成したら、ShiftJISで書き込まれてしまっていました。Windows XPなら大丈夫だったんですが・・・



さて、convmvでファイル名の文字コードを変換したあと、SambaやWebDAVから正しく見えるかどうか、やっぱり確認したいです。うまくいけば、それでいいし、おかしくなったら、元に戻したい、というわけ。



そこで、こんな方法を試してみました。



  • findコマンドを使って、文字コードを変更したい全ファイルのハードリンクを作成しておき、


  • ハードリンクの方のファイル名を、convmvで変換する


  • 変換されたほうのファイルに、正しくアクセスできるか、動作確認する


  • 正しくアクセスできたなら、ハードリンクのほうを残して、オリジナルのほうは削除


  • 問題があったら、ハードリンク側を削除。オリジナルのほうは、そのまま残っている

ところで、なぜハードリンクを使ったかというと、こういう風に、いらないほうを削除してしまえば、もうそれで事はすんでしまう、っていうのもあったのですが、実は、Apacheの設定で、シンボリックリンクは禁止にしてあったので(Options FollowSymLinksを指定していない)、シンボリックリンクのファイル名を変更しても、そもそもWebDAVからアクセスできなかったから、という理由でした。



さてさて、findコマンドは、使い方を知っているか知らないかで、Unix使いとしてのレベルに大きな差がでるコマンドなわけですが(すごい便利なコマンドだけど、けっこう使い方が難しい)、使いこなしているつもりでいたのに、今回、えー?こんなことを今まで知らなかったんだ!? と恥ずかしい思いをしました。



ハードリンクが作成される先の仮のディレクトリを$TARGETとするとして、ディレクトリのハードリンクは(普通は)作成できませんから、ディレクトリだけ、あらかじめ作っておくことにしました。



こんなかんじで



find . -type d -exec echo mkdir $TARGET/{} \;



というコマンド(echoは実行する前にどんなコマンドが実行されるのか確認したかったのでつけただけ)を実行してみました。



カレントディレクトリから、こういうファイル・ディレクトリ構造



./あいうえお/かきくけこ/さしすせそ.txt
./あいうえお/たちつてと.jpg



setenv TARGET /home/ttt/CONV.tmp



find . -type d -exec echo mkdir $TARGET/{} \;



実行してみると



mkdir /home/ttt/CONV.ttt/
mkdir /home/ttt/CONV.ttt/
mkdir /home/ttt/CONV.ttt/



としか表示されません。これまで、「{}」としか指定したことがなかったので、「{}」に何かつけたらダメなのかと思ったのですが、FreeBSDのfindのmanを読むと、わざわざ、ちゃんとできる、と書いてありました。


5分ほど悩む。findのソースコードも眺めた。



わかりました。てゆーか、思い出しました。



「{~}」ってのは、シェルで意味のある記号でした。こんな働きをします。



% echo {ABC}
ABC



% echo {A,B,C}
A B C



% echo X{A,B,C}
XA XB XC







中学校の数学で教わる多項式展開みたいなことがおこるんですね。



ところが



% echo {}
{}



と、「{}」のときだけは、{}がでてくるんですね。「{}」だけは特別で、シェルに食べられずに、そのままでてくるんです。

へ~ そーだったんだー
これまでは偶然うまくいってただけだった?!
最初に読んだ参考書(「UNIXプログラミング環境」かもしれない)が{}という書き方だったので、そのまま丸暗記してたのでした


どうやら"~"で囲めば、「{}」の働きを封じることができるらしいので、

% find . -type d -exec echo mkdir "$TARGET/{}" \;

で確認すると

mkdir /home/ttt/CONV.ttt/.
mkdir /home/ttt/CONV.ttt/./あいうえお
mkdir /home/ttt/CONV.ttt/./あいうえお/かきくけこ

となって、大丈夫そうなので

% find . -type d -exec mkdir "$TARGET/{}" \;

にてディレクトリを作成。

その後、ファイルのハードリンクを作成します。



% find . \! -type d -exec echo ln "{}" "$TARGET/{}" \;

ln ./あいうえお/かきくけこ/さしすせそ.txt /home/ttt/CONV.ttt/./あいうえお/かきくけこ/さしすせそ.txt
ln ./あいうえお/たちつてと.jpg /home/ttt/CONV.ttt/./あいうえお/たちつてと.jpg


どうやら大丈夫なので、実行。

% find . \! -type d -exec ln "{}" "$TARGET/{}" \;



あとは、$TARGETのほうのディレクトリにたいして、convmvを実行して、文字コードを変えても大丈夫か、じっくりと動作確認をする、というわけ。





ちなみにfind ・・・-exec echo ・・・したのを、 ・・・ | /bin/sh とパイプでシェルにつないじゃうと、マルチバイト文字の中に、またシェルのメタキャラがまじっている可能性があるので、まずいとおもいます。-exec echoじゃなくて、-execでそのまま実行しちゃうからこそ、うまくいく、と。

勘違いだったらすみません。ちょっと自信ないです。







ちなみに、convmvは、こんな風に使うそうです。



# convmv -r -f euc-jp -t utf-8 .



で確認したのち(文字化けして見えるので、確認にならないと思うのですが・・・)



# convmv --notest -r -f euc-jp -t utf-8 .



で、実際に変換されます。



エンコーディング名は、こんなふうに一覧表示されるそうです。



# convmv --list
7bit-jis
AdobeStandardEncoding
AdobeSymbol
AdobeZdingbat
ascii
ascii-ctrl
big5-eten
big5-hkscs
cp1006
cp1026
cp1047
(以下略)









0 件のコメント:

コメントを投稿