未だにPerl使いである。
別に大好きな訳ではない。似たようなことの出来るスクリプト言語を他に覚えてないだけだ。
今からアレ系を新しく覚えるなら、まあ、Pythonなのかな。PHPも便利そうだ。どちらも別にさほど苦労せず覚えられそうな甘い気持ちは若干あるが、必要に迫られないといまいちなあ。
まあそれに、大好きってほどではないけど、気を抜いて書き捨てやすいPerlの緩さは結構好きだ。Larry Wallのアレっぷりも割と。
で、ActivePerlを使っている。まあWindowsだし。だいぶ昔に入れたっきりだが、めんどくさいので更新してない。別に鯖でもないし平気だろう。5.10.0ならそこそこ新しい方だろうし。
そして、書きっぱ気味のスクリプトなどでバリバリ使うのだが、globがどうもバグってる。File::Glob::Windowsとか入れても駄目。ディレクトリ部に特定の文字を含むglobを掛けるとおかしくなる。どうせマルチバイトの問題だろう。新しい奴なら直ってるかもしれんけど。
んで、めんどくさいんで、どうにかしようと試した。どうにかなった。DirHandleなりopendirなりで一括readしたのをgrepでもすればいいようだ。めでたしめでたし。具体的には、
sub glob_re ($$) { my ( $dir, $re ) = @_; my $dh = new DirHandle $dir; return grep /$re/, $dh->read; }
こんな感じか。呼び出しは
glob_re '.', qr/\.txt$/i;
みたいな。動作確認しないままだらだら書いてるが、気持ちが伝わればいいのではなかろうか。さっき似たようなコード書いて動いたしさ。つーか正規表現globなんて既製モジュールありそうなくらい普通に欲しい関数だよな。まあいいか、短いから自作でも。Perlだし。
ああ、いかん。今は5.10用スクリプトをuse utf8でUTF-8対応テキストエディタで書いてるから、Windowsだとエンコード掛けないと日本語ファイル名でやばかったんだよな。つーか元々それが目的じゃないか(笑)。ついでにglob互換にするなら.
と..
も除外してパスも付けないとな。
sub glob_re ($$) { my ( $dir, $re ) = @_; my $dh = new DirHandle encode 'cp932', $dir; return map { File::Spec->canonpath( File::Spec->catfile( $dir, $_ ) ) } grep /$re/, File::Spec->no_upwards( map { decode 'cp932', $_ } $dh->read ); }
こうですね。多分。動作確認してないけど。つーかどんどん書き捨て臭が。まあいいか、Perlだし。
Strawberry Perl 5.24.1.1-64bitでも同じように日本語含むパス名使うと、glob使うとおかしくなります。
Strawberry Perl 5.20.3で、↓でglobできます(環境はWin10)。
※ソースコード自体はutf-8で保存しています。
#!perl
use utf8;
use Encode;
$targetPath = “C:\\temp\\work\\あ いうえお”; # 「あ」の後ろに半角スペース。
$targetPath = Encode::encode(“cp932”, $targetPath);
my @files = glob(qq#”$targetPath”/*#);
foreach(@files){
print “$_\n”;
}
ポイントは2つで、先ずはglobに渡すパスの文字コードをcp932(shift_jis)にしてあげる事と、もう1つは、パスに空白が含まれる場合は、パス全体をダブルクォートで囲ってあげる必要があるという点。