ようへい

2013年8月6日火曜日

Rubyで、パスに特殊文字を含むファイルの存在確認を行う

ファイルがあるのに「No such file or directory」

Windows上でRubyを使っていると、ファイルパスに特殊文字を含んだファイルを扱う事がある。
e.g.,
».htm
®.htm
™.htm
これらのファイルをRubyスクリプトの引数で渡してもファイル名が化けてしまったりしてうまく扱えない。
こんなRubyスクリプトに渡してみる。
#!ruby
# -*- coding: utf-8 -*-

puts File.basename( ARGV[0] )
puts File.exist?( ARGV[0] )
puts File.exist?( ARGV[0].dup.force_encoding( 'utf-8' ) )
puts ARGF.path
環境はWindows 7、Ruby 1.9.3、Encoding.locale_charmapCP932。 このスクリプトに先のファイル名を与えると以下のような結果になる。
».htm
≫.htm
false
false
file_check.rb:7:in `path': No such file or directory - ≫.htm (Errno::ENOENT)
 from file_check.rb:7:in `<main>'
®.htm
R.htm
false
false
file_check.rb:7:in `path': No such file or directory - R.htm (Errno::ENOENT)
 from file_check.rb:7:in `<main>'
™.htm
R.htm
false
false
file_check.rb:7:in `path': No such file or directory - R.htm (Errno::ENOENT)
 from file_check.rb:7:in `<main>'
UTF-8のバイナリで表すと、以下のように文字が変化してしまっている。
».htm -> ».htm (0xC2 0xBB -> 0xE2 0x89 0xAB)
®.htm -> R.htm (0xC2 0xAE -> 0x52)
™.htm -> R.htm (0xC2 0xE2 0x84 0xA2 -> 0x52)
どーしたらいいんでしょうか。

できる対処法

とりあえず、Rubyをキックするバッチを作って、その中でテンポラリディレクトリにファイルを複製、リネームして、そのファイルをRubyスクリプトに与えることで対処。
こんなかんじ。
SET FDATE=%date:~2%
SET FTIME=%time:.=-%
SET FTIME=%FTIME: =%
SET TEMP_F="%TEMP%\%FDATE:/=-%_%FTIME::=-%%~x1"

COPY %1 %TEMP_F%
C:\Ruby193\bin\ruby file_check.rb %TEMP_F%
DEL %TEMP_F%
Rubyの中で、オリジナルのパス名が必要なら、こんなカンジ。
SET FDATE=%date:~2%
SET FTIME=%time:.=-%
SET FTIME=%FTIME: =%
SET TEMP_F="%TEMP%\%FDATE:/=-%_%FTIME::=-%%~x1"

COPY %1 %TEMP_F%
C:\Ruby193\bin\ruby file_check.rb %TEMP_F% %1
DEL %TEMP_F%
とりあえずファイル読めるようになる。
もっと効率良い方法あると思うので、教えてください。
関連記事