Ruby:使用特殊字符重命名文件

时间:2011-12-13 21:00:30

标签: ruby

我在ruby版本1.9.3p0中有这个程序,它根据正则表达式条件重命名从shell传递的文件(发送到)。工作正常,除非文件名中包含特殊字符。

ruby RegExpRename.rb "32. Esther Verhoef - Déjà vu.epub"

给出错误

/RegExpRename.rb:29:in `rename': No such file or directory - (32. Esther Verhoef - DÚjÓ vu.epub, test) (Errno::ENOENT)
from C:/Users/peter/AppData/Roaming/Microsoft/Windows/SendTo/RegExpRename.rb:29:in `block in <main>'
from C:/Users/peter/AppData/Roaming/Microsoft/Windows/SendTo/RegExpRename.rb:18:in `each'
from C:/Users/peter/AppData/Roaming/Microsoft/Windows/SendTo/RegExpRename.rb:18:in `<main>'

编码是罪魁祸首,我的windows cp是CP850,在DÚjÓ中改变了似曾相识 我不知道怎么解决这个,请帮忙。 这是程序

# encoding: CP850
require 'find'
require 'fileutils'
require 'Win32API'

def get_long_win32_filename(short_name)
  max_path = 1024
  long_name = " " * max_path
  lfn_size = Win32API.new("kernel32", "GetLongPathName", ['P','P','L'],'L').call(short_name, long_name, max_path)
  return (1..max_path).include?(lfn_size) ? long_name[0..lfn_size-1] :  short_name
end

ARGV.each do|a|
  long = get_long_win32_filename(a)
  result = long.gsub(/(\w+)\s*,\s*([^\-]+)\s*\-\s*(.+\.[a-zA-Z]{3,4})/i, "\\2 \\1 - \\3")
  if result == long
    result = long.gsub(/(\d+\. +)(.*)/i, "\\2")
  end

  if result != long
    if File.exist?(result)
      puts "File #{result} already exists.  Not renaming."
    else
      File.rename(a, long)
      puts long + " ===> " + result
    end
  else
    puts long_name + " don't have to be renamed"
  end
end
sleep 15

2 个答案:

答案 0 :(得分:2)

NTFS内部编码始终是unicode。

因此,如果您使用NTFS作为文件系统,那么您拥有系统CP850并不重要。

尝试在ruby代码文件中设置# encoding: utf-8

答案 1 :(得分:0)

Pfew ..不知道我是否应该感到高兴,我终于找到了它,或者说红宝石让它变得如此困难。 无论如何,这是溶剂。

问题是当rubyscript在Windows7命令提示符(或shell)中获取参数时,它(在我的情况下)编码为CP1252,我不知道为什么。因此,如果我用CHCP 1252更改我的CP,脚本运行正常,但当然没有解决方案,所有特殊字符都打印错误。

解决方案:我告诉ruby编码IS CP1252并转换为我的语言环境CP(在我的情况下为CP850) 我希望可以检测CP1252而不是硬编码,这是一个更通用的解决方案。 有什么建议吗?

这里我用来测试它的程序,我传递参数“déjà.epub”,文件IS被重命名为这样。

a = ARGV[0].dup.encode(Encoding.locale_charmap)