• ベストアンサー

Windows漢字フォルダ名の扱い(その2)

先回に引き続きお伺いします。 ■フォルダツリー体系が次のようになっているとき、 D:\TEMP ├─フォルダ名の末尾に機能 │ test1.txt ├─フォルダ名の末尾に表 │ test2.txt ├─途中に機能がある │ test3.txt └─途中に表がある test4.txt ■次のスクリプトを処理させるのですが、 #!perl use strict; &subdir($ARGV[0]); sub subdir { my($dir) = $_[0]; opendir(DIR,"$dir") || die "'$dir' $! stopped"; foreach(sort readdir(DIR)){ next if(/^\.+/); # '.' '..' はパス if(-f "$dir\\$_"){ print "'$dir\\$_'\tはファイルです\n"; }elsif(-d "$dir\\$_"){ print "'$dir\\$_'\tはフォルダです\n"; &subdir("$dir\\$_"); }else{ print "'$dir\\$_'\tは何ですか?\n";#出て欲しくない } } closedir(DIR); } ■結果は、次のようになります。 (※フォルダ名の末尾に特殊な漢字コードがある所が判定できない) C:\>test.pl d:\temp 'd:\temp\フォルダ名の末尾に機能' は何ですか? 'd:\temp\フォルダ名の末尾に表' は何ですか? 'd:\temp\途中に機能がある' はフォルダです 'd:\temp\途中に機能がある\test3.txt' はファイルです 'd:\temp\途中に表がある' はフォルダです 'd:\temp\途中に表がある\test4.txt' はファイルです 先回、色々と教わったこと use encoding "Shift_JIS"; や 局所的に $dir を decodeさせるなどしても上手く行きません。良い方法があれば教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.6

ファイル名が'一覧表'とかみたいになっている場合の対処について考えてみました。 相変わらずですが^^ ---------------------------------------------------------------- #!perl use strict; use File::Basename; &subdir($ARGV[0]); sub subdir { my($dir) = $_[0]; my $wk; opendir(DIR,"$dir/") || die "'$dir' $! stopped"; foreach(sort readdir(DIR)){ next if(/^\.+/); # '.' '..' はパス my ($base,$path,$type) = fileparse("$dir/$_", qr{\..*}); $wk = "$dir/$_" . ($type ? "" : "\.");#拡張子が無い場合ピリオドを付ける if(-d "$dir/$_/"){ print "'$dir/$_'\tはフォルダです\n"; &subdir("$dir/$_"); }elsif(-f $wk){ print "'$dir/$_'\tはファイルです\n"; }else{ print "'$dir/$_'\tは何ですか?\n";#出て欲しくない } } closedir(DIR); }

goku3
質問者

お礼

なるほどー #拡張子が無い場合ピリオドを付ける がミソですね。 fileparse("$dir/$_", qr{\..*}); の関数でファイル名が正しく分離できるんだったら、 今回のような問題もすんなり対応できるようにperl本体が進化してくれれば良いですね。 あ、だから、jperlがあるのか・・・Own Goal!!(^^;

その他の回答 (5)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

-fや-d, opendir などを使った場合にはCのランタイムライブラリ(さらにはもぐってWindowsAPI)を呼び出すのですが、これには Unicode文字列を渡せない(少なくとも現状では)ので、今回のケースでは use encoding や decode することは対策にはなりません。 で、機能とか表はバイト列で見ると '\' で終わっています。Perlの内部で -fなどの処理をするときに末尾の'\' を '/' で置き換える等の処理をしています(ライブラリのバグ回避等のため)。 このとき、ShiftJISの文字列であるかどうかを気にしていないので、 「機能」とかが末尾に来ると置き換えてはいけないものを置き換えてしまうので、誤動作することになります。 WindowsAPIやライブラリのレベルではパスの区切りとして'\'でも'/'でも 許すので、Perlでも区切りとして'/’が使えるようになっています。 対策としては、BLUEPIXYさんがしているように、末尾に'/'を加えて みるというものなどがあります。ただ、ディレクトリ名ではなく ファイル名が'一覧表'とかみたいになっていると多分どうしようも ないです。 以上重箱の隅でした。

goku3
質問者

お礼

なるほど勉強になりました。 ありがとうございます。 >>ただ、ディレクトリ名ではなくファイル名が'一覧表'とかみたいになっていると多分どうしようもないです。 確かに、そうですね・・・ ただ今回の場合は、MS系の文書ファイル類が主なので、必ず半角英数字で拡張子が付くため、結果オーライの感じです。 (”ぎじゅつ者”的には、少し許せないところではありますが) ありがとうございました。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

sub subdir { my($dir) = $_[0]; opendir(DIR,"$dir/") || die "'$dir' $! stopped"; foreach(sort readdir(DIR)){ next if(/^\.+/); # '.' '..' はパス if(-f "$dir/$_"){ print "'$dir/$_'\tはファイルです\n"; }elsif(-d "$dir/$_/"){ print "'$dir/$_'\tはフォルダです\n"; &subdir("$dir/$_"); }else{ print "'$dir/$_'\tは何ですか?\n";#出て欲しくない } } closedir(DIR); } としてみるとか

goku3
質問者

お礼

encodeを使わない方法もあるのですね。 示して頂いたスクリプトで、目的のことができるようになりました。 夜遅くにご回答ありがとうございました。

goku3
質問者

補足

追伸ですが、 Windows用でも、perlスクリプトの中では、デリミタを'/'としても良いのですね・・・ これまでは、わざわざ、 $_DLM = ("$^O" =~ /linux/i)? "/" : "\\";# OS別パスデリミタ のようなことをしていました・・・

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

「表」も「能」も、S-JISでは第2バイトが「\」です。 ですので、-dまたは-f付きif文は、falseを返します。 perlでは、漢字を含む文字列を処理する際、文字列がS-JISだと漢字の第2バイトが悪さをして正常に動きません。 一時的に文字列をS-JIS以外の文字セットに変換するなどして、文字列中に「\」や「|」などの文字が入らないようにして下さい。

goku3
質問者

補足

深夜に素早いご回答、ありがとうございました。 >>一時的に文字列をS-JIS以外の文字セットに変換するなどして、 ですが、やってみたこととして、 use Encode; を使って、 my($dir) = Encode:decode("s-jis",$_[0]); opendir(DIR,"$dir") || die "'$dir' $! stopped"; foreach(sort readdir(DIR)){ next if(/^\.+/); # '.' '..' はパス $_ = Encode:decode("s-jis",$_); if(-f "$dir\\$_"){ print "'$dir\\$_'\tはファイルです\n"; }elsif(-d "$dir\\$_"){ print "'$dir\\$_'\tはフォルダです\n"; &subdir(Encode:encode("s-jis","$dir\\$_")); }else{ print "'$dir\\$_'\tは何ですか?\n";#出て欲しくない } のようにしてみたのですが、これでも上手く行きませんでした。 良い指定の方法などがあれば教えてください。よろしくお願い致します。

  • necomimi
  • ベストアンサー率41% (633/1540)
回答No.2

失礼しました、そういう問題ではないのですね。 #1は無視で

goku3
質問者

お礼

いえ、そうでもないですよ。 私も一瞬、「あ、そうか」と思いましたので。 ただ、statに渡した際にも、この変な文字がある場合は やはり問題が出るようですので、残念ながら、という感じです。 ありがとうございました。 (#2に対して、「自信:自信あり」は笑わせて貰いました)

  • necomimi
  • ベストアンサー率41% (633/1540)
回答No.1

フォルダかファイルかを見分けるだけならstatを使ったらどうでしょう?

関連するQ&A