Perl つかって 8 年目でディレクトリをコピーをしようとしてハマる
ディレクトリをコピーする機会がなかった
意外なことに、いままでディレクトリのコピーをする用件がなかった。
で、ハマった。
Perl でファイルコピーと言ったら File::Copy という標準モジュール。それで事足りてきた 8 年間。
だもんで、File::Copy でディレクトリもコピーできるだろうと・・・思ったけど、うまくいかない。
「ははーん、これは先に移行先のディレクトリ 作っておけってことね」と思って先行してコピー先のディレクトリを作っておくもダメ。
Mac 上で書いて、Windows 上で動かすコードだったので、文字コードの違いかなー?
と思うも違う。むー
で、File::Copy::Recursive モジュールを使ってあっさり解決した。そうか、File::Copy でディレクトリのコピーはできんかったのか・・・できると思い込んでた。
せっかくなので Windows で日本語ファイル名・フォルダを扱う時の注意
Windowsの文字コードは cp932
ってやつで、ファイル名やパスもこの cp932
です。
そう、ファイル名だけじゃなくて パスも cp932
でエンコードしてあげる必要があります。
フォルダのコピーがうまくいかない時、ちゃんとファイルを認識しているんかな?と思って -e $path
ってファイルテスト演算子使ってみたのですが、みごとに認識しておりませんでした。
-e encode('cp932', $path)
とすることでちゃんとファイルパスを認識してくれました。
コードにするとこんな感じです。utf8
で保存したスクリプトを Windows で実行ってのを想定してます。
#!/usr/bin/env perl use strict; use warnings; use utf8; use Encode qw/encode/; use File::Spec; # ダブルクォーテーションだと \ をエスケープ文字と認識してしまい失敗するよ my $path = 'D:\Desktop\新しいフォルダー (2)'; if ( -e $path ) { print "$path is exist\n"; } else { # Windowsで実行すると、ここを通る(文字化けもする) print "$path is not exist\n"; } # utf8のスクリプト上に書かれたパス(9行目)を、パス含めて cp932 でエンコード my $cp932_path = encode( "cp932", $path ); if ( -e $cp932_path ){ # Windowsで実行すると、ここを通る(文字化けしない) print "$cp932_path is exist\n"; } else { print "$cp932_path is not exist\n"; }
追記
さーてバリバリ続き書いてくかー!
って思ったら、ファイルコピー失敗。おいおいなんだよー、ファイルコピーは問題ないはずだろ!・・・と思ったがこういうオチだった。
コピー先の容量不足。
ファイルコピー道は険しい。