filenameプラグマの使い途(その2、ファイル名のエスケープ処理)

filenameプラグマの使い途(その2、ファイル名のエスケープ処理)

 たとえばsamba上にあるファイルに対してローカルで処理するコードを書いていたけど、どうせならサーバで動かせばいいんじゃね? と思って実行しようと思ったらファイル名のエンコードが違ってるってのは良くあることだと思う(よね?)。

 cp932とeucjpの違いとかなら

use encoding 'cp932';
use filename \&_convert;
BEGIN {
    require Encode;
    my $enc = Encode::find_encoding($^O eq 'MSWin32'? 'cp932': 'eucjp');
    sub _convert {
        my $filename = shift;
        if (utf8::is_utf8($filename)) {
            $enc->encode($filename);
            }
        else {
            $enc->decode($filename);
        }
    }
}

――とかで対応できるし、何らかのエスケープされている時は

use encoding 'cp932';
use filename \&_convert;

BEGIN {
    require Encode;
    my $enc = Encode::find_encoding('cp932');
    my $_convert;
    if ($^O eq 'MSWin32') {
        $_convert = sub {
            my $filename = shift;
            if (utf8::is_utf8($filename)) {
                $enc->encode($filename);
            }
            else {
                $enc->decode($filename);
            }
        };
    }
    else {
        $_convert = sub {
            my $filename = shift;
            if (utf8::is_utf8($filename)) {
                my $str = $enc->encode($filename);
                $str =~ s/([\x80-\xff])/':' . unpack('H2', $1)/eg;
                $str;
            }
            else {
                $filename =~ s/:([a-f\d]{2})/pack('H2', $2)/eg;
                $enc->decode($filename);
            }
        };
    }
    sub _convert { goto &$_convert; }
}

――なんてこともできて、ちょっと便利。

 Wikiでマルチバイトな項目をファイルに出力してる場合はURIエスケープしてたりするので、そういうファイルを開くのにも使える。