• 締切済み

Perl で File::Find できない

Perl 初心者です。Windows 上で、親ディレクトリを ARGV に引き渡してすべてのサブディレクトリを再帰的に処理するスクリプトを作成しましたが、名前に「表」の漢字が含まれているディレクトリだと、処理が失敗します(その他のディレクトリでは正常に動作します)。調べたところ、以下のサイトで指摘されている問題らしく、いろいろと書き直しては見たのですがうまく動きません。ご教示いただけないでしょうか。 参照したサイト -------------- 「WindowsのPerlで日本語パス名を処理すると0x5C文字でつまずく」 http://raven.air-nifty.com/night/2009/12/windowsperl0x5c.html 作成したスクリプト(抜粋) ------------------------- my $top_dir = $ARGV[0]; find( \&hogehoge, $top_dir );

  • Perl
  • 回答数1
  • ありがとう数2

みんなの回答

  • Gotthold
  • ベストアンサー率47% (396/832)
回答No.1

Windows環境のPerlでは ファイル名やディレクトリ名やコマンドライン引数@ARGVは Windows-31J(またはCP932。厳密には違うけどShift_JISと呼ばれることも)という文字コードで扱われますが、 File::Findは(というかPerl全体的に)Windows-31Jを考慮していないので うまく動作しないのだと思います。 opendirとかを駆使して自力で再帰処理するか、 Win32::Unicode::Dir::findWのようなunicodeで処理できるモジュールを使うかだと思います。 Win32::Unicode::Dir - search.cpan.org http://search.cpan.org/~xaicron/Win32-Unicode-0.38/lib/Win32/Unicode/Dir.pm 正直なところ、Perlで日本語を含んだファイル・ディレクトリの処理は初心者には厳しいと思います。 私もWindows上でPerlを使うことはありますが、 ファイルの再帰リストアップとかはやるとしてもPerlの外(呼び出し側でループを回すとか、リストをファイルで持つとか)でやりたいですね。 Perlの外でやるという意味では、 print `dir /b /s $ARGV[0]`; は解の1つかもしれませんが、もはやPerlを使っていると言えない気も^^; (dirコマンドはWindowsのコマンド)

cat-rice
質問者

お礼

ご回答ありがとうございました。モジュールがあるのですね。確かに Win32::Unicode::Dir をCPAN からインストールするのが一番早いと思いましたが、サーバー側の原因か、失敗しました。print `dir /b /s $ARGV[0]`; を使う方法も、少し試しましたが自分の能力ではできません。これ以上時間もかけられないため、私では現状無理なようです。ありがとうございました。

関連するQ&A

  • sedやperlでの2バイト文字を含む変換

    こんにちは。 sedコマンドは、texに付属していた日本語対応のものを使用しており、 perlはWindows用のActive Perl v.5.12.2を使用しています。 カレントディレクトリにあるファイルやフォルダにおいて、 名前を一括して変換したいと思い、以下のようなNameConv.batというバッチスクリプトを作成しました。 ____________________________________________________________ @echo off for /f "delims=" %%a in ('dir /b !opt!') do ( for /f "usebackq delims=" %%b in (`echo %%a^| sed -e "s/%~1/%~2/g"`) do ( move /y "%%a" "%%b" 1>nul 2>nul if not "%%a"=="%%b" echo 「%%a」→「%%b」 ) ) ____________________________________________________________ このバッチスクリプトを NameConv.bat " " "_" の様にして呼び出すと上手く行きました。 (この場合は、カレントディレクトリの全てのディレクトリとフォルダの名前において、 スペースがアンダーバーに変換されました。) ところが、 NameConv.bat "スペース" " " のように、第一引数に変換文字列に2バイト文字を使用すると、 以下のようなエラーメッセージが出て上手く行きませんでした。 sed: -e expression #1, char 14: Unterminated `s' command どうやら、 echo %%a| sed -e "s/スペース/ /g" といったコードは、上手く行かなかったようです。 そこで、この問題を解決しようと、以下のようなNameRep.plというPerlスクリプトを作成しました。 ____________________________________________________________ #日本語を扱うために必要な設定 use encoding "cp932"; use open ":encoding(cp932)"; use open ":std"; map{ binmode($_,":crlf"); } qw/STDIN STDOUT STDERR/; #置換操作 $name="$ARGV[0]"; $name =~ s/$ARGV[1]/$ARGV[2]/g; print "$name"; ____________________________________________________________ そしてこのスクリプトを for /f "delims=" %a in ('dir /b') do ( @perl NameRep.pl "%a" "スペース" "_" ) の様にしてコマンドラインから呼び出すことで、「スペース」という文字列が、 きちんと処理できるかを試したところ、以下のようなエラーメッセージが出ました。 Unmatched [ in regex; marked by <-- HERE in m/\x{00d8}\x{00f9}\x{005b} <-- HERE \x{00d8}/ at C:\Users\kei\NameRep.pl line 11. どうやら $name =~ s/$ARGV[1]/$ARGV[2]/g; の部分で、$nameや$ARGV[1]に2バイト文字が含まれていると、上手く行かないようです。 #日本語を扱うために必要な設定 以下のコードブロックで、シフトJISに対応できるはず(少なくとも今までは問題なく扱えました) なのですが、何故か上手く行きません。 そこで、sedコマンドやperl、特にperlにおいて、シフトJISコードでの2バイト文字の扱い方を御存じの方に、何かアドバイスを頂きたいと考えています。 長くなりましたが、どうぞよろしくお願い致します。

    • ベストアンサー
    • Perl
  • (visual)C++から(active)perlを呼ぶ

    Vista sp1 64 bit, visual C++ 2008 express, active perl 5.1を使用しています。 しばらくの間active perlを使ってテキスト処理のスクリプトを書き溜めてきました。 最近になってC++ を使うようになり、今後はC++中心にプログラミングをしていこうと思っています。 ただ、これまで書き溜めたperlスクリプトをどうにかしてC++で再利用できないかと思っています。またテキスト処理に関してはC++よりやはりperl が優れていると感じ、C++ のプログラムを主体として必要に応じてその中にperlのスクリプトを組み込みたいと考えています。 たとえばテキストファイルを読み込みや最終的な出力するのはメインのC++で書き、各行のテキスト処理はC++からperlのサブルーチンにデータを渡して処理するというような形です。 perlのドキュメントを見る限りではperlembedがこの目的に適しているようでした。 http://perldoc.jp/docs/perl/5.10.0/perlembed.pod サンプルコードなども書いてあるのですが、どうやらunix環境、gcc(?)の例のみのようです。 windows環境でvisual C++ とactive perlを用いて C++からperlを呼び出すようなプログラムを書くにはvisual c++の設定をどのようにしたらよいでしょうか?

  • chdirがうまくできない

    はじめまして。hiro0777と申します。 perl初心者です。 お恥ずかしい内容なのですが、アドバイスいただければと思います。 環境はWindowsXP&Cygwinです。 質問内容:chdirがうまくできない。(ディレクトリ移動がうまくいかない) ・カレントディレクトリには、いくつかのサブディレクトリがあり、  サブディレクトリ名のみが書かれたファイル(dir.txt)がある。  dir.txtには「480iacrlc2」「480iacscan」といったディレクトリ名が1行ずつ記載。 ・dir.txtから1つずつサブディレクトリ名を読み取り、  そのディレクトリに移動し、ファイル処理をする。 #ここでコマンド引数にdir.txtを指定。 open(DIR, $ARGV[0]) || die "can't open $ARGV[0]\n"; while(1){ chomp($dir = <DIR>); #print "$dir\n"; chdir("$dir") or die "Cannot change directory '$dir'\n"; #system("pwd");  ###以降ファイル処理。 } 上記のようにやったのですが、うまくディレクトリを移動してくれません。 ちなみに以下のように直接ディレクトリ名を指定した場合はうまくいきました。 open(DIR, $ARGV[0]) || die "can't open $ARGV[0]\n"; while(1){ $dir = "480iacrlc2";#ファイル名を直接指定したら移動した。 chdir("$dir") or die "Cannot change directory '$dir'\n"; #system("pwd");  ###以降ファイル処理。 } テキストの扱いかたがいけないのかなぁと想像しているのですが。 どなたかご教授いただければ幸いです。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • Rubyのスクリプト

    Rubyを使って、ディレクトリを順に処理していくスクリプトを作ろうとしています。 下記は、perlのものです。 chdir("C:/data"); opendir(DIR, "./"); @myfolderlist= grep(-d, readdir(DIR)); close(DIR); foreach $myfolder(@myfolderlist){ if(($myfolder ne ".") && ($myfolder ne ".." )){ print "$myfolder\n"; } } これに対応するような、かつRubyらしい(foreachを使う)スクリプトを作りたいと考えます。 Dir.foreach('C:/Data'){|item| item.chomp! print item,"\n" } 上記のRubyスクリプトの問題は、ディレクトリのみならず、そこに存在するファイルまで出してしまいます。 Rubyにおいて、ディレクトリ」のみを持ってくるには、どのようにすれば良いでしょうか? 宜しくお願いいたします。

  • Perl言語を使ったハノイの塔の解き方

    Perl言語(再帰処理)を使ったハノイの塔の解き方を教えてください。 引数は3でお願いします。 他の言語での解き方は解説サイト等があるのですが、Perl言語の解説はあまり載っていないので是非教えてください。

  • Perlで特定行から特定行までを抜き出したい

    皆さんのお知恵をお貸し頂ければ幸いです。 Perlで以下のようなことをしたいと考えています。 例えば、次のようなテキストファイルがあったとします。 example.log ================================== aaaa hogehoge test okok perl script ================================== 上記ファイルを読み込んで、「hogehoge」から「perl」の間に挟まれた行だけ抜き出したいのです。 イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。 このような場合、どういう風にすればいいのでしょうか? 恐れ入りますが、ご教授頂ければ幸いです。 それでは、どうぞよろしくお願い致します。

    • ベストアンサー
    • Perl
  • perlスクリプト内の変数を別のCプログラム中の変数に代入するには?

    次のようなことは可能でしょうか。もし可能でしたらどのようなスクリプトを書けばよいでしょうか。 test.cというCプログラムがあってこの中ではprintf("x=%d",k);と出力するようになっています。 perlスクリプト内で同様に変数kを定義してforループでまわします。そのループ内でtest.cファイルを開きtest.c内の変数kにperlで定義した変数kの値が代入されてコンパイル・実行するようなスクリプトを組みたいのですが。 なぜこのようなことをしているかというと太郎君がk歳のときのj月のときの身長を記録すると言うようなことをやっているためです。身長の計算は別のCプログラムでやっています。perlスクリプトで1歳、2歳、3歳というディレクトリを作って、各ディレクトリに1月身長.dat、2月身長.dat、・・・12月身長.datというデータをおくことを考えています。

  • perl-cgi「日時によるファイル操作」について

    perl-cgi「日時によるファイル操作」について perl-cgiで、あるディレクトリ中のファイル更新日が最も若い2ファイルを表示して、それ以外を削除したいのですがどのようにすればよいでしょうか? #調べたいディレクトリを読み込む。 $Dir = "./cache"; opendir DIR,"$Dir"; my @alldir = readdir DIR; close DIR; #ファイル(パス)名と作成日時を求める。 #最新2つのファイルパス(名)を表示する。 print "NewFile".ファイルパス1; print "<HR>"; print "OldFile".ファイルパス2; #最新2つ以外は全て削除 unlink($_); exit(0);

    • ベストアンサー
    • Perl
  • perlの正規表現

    はじめまして現在Perlでスクリプトを作成しています。 やりたいことは ・ユーザがコマンドラインより文字(ユーザID)を入力 ・その文字列が#getent passwdの結果にあるか無いかで処理を分ける です。 #getent passwd | grep hogehogeの結果は下記のとおりです。 hogehoge:x:1210:104:staff:/home/data/staff/hogehoge:/bin/bash これより先頭の[hogehoge]とユーザが入力したhogehogeが完全一致すれば問題ありません。 正規表現を調べましたが文字列での一致はあるのですが引数での文字列が調べることが出来ませんでした。 よろしくお願いします。 print "Enter User ID\n"; $id = <STDIN>; chomp($id); $cmd =`getent passwd | grep $id`; system($cmd); if ($cmd == ~ /^$id/) { print "There is not ID\n"; } else { print "Your ID is there\n"; }

  • perlのダウングレード方法

    VMware上でUbuntu10.04を使っている者です。 いま、ある都合により、既にインストール済みのperl5.10.1から 5.8.8にダウングレードしたいと考えているのですが、 それが中々うまくいきません。 具体的には、 [http://www.cpan.org/src/5.0/] から perl-5.8.8.tar.gzをダウンロードしてきて展開後、 作業DIRに入って、 >./Configure -Dprefix=/usr/local/perl/ -de >make としたところで、 Making x2p stuff make[1]: ディレクトリ `/usr/local/perl/perl-5.8.8/x2p' に入ります You haven't done a "make depend" yet! make[1]: *** [hash.o] エラー 1 make[1]: ディレクトリ `/usr/local/perl/perl-5.8.8/x2p' から出ます make: *** [translators] エラー 2 と返されます。 Linux初心者で、 ここからどう対処していけば良いか分からないので どなたかご教授いただけないでしょうか? 宜しくお願い致します。

専門家に質問してみよう