Как получить длинное имя файла от ARGV
Я хочу сделать инструмент, который принимает некоторые имена файлов в качестве параметров, но когда я использую этот код:
ARGV.each do|a|
puts "Argument: #{a}"
end
и я использую перетаскивание или "отправить" в Windows, я получаю короткое имя файла. Так что файл как "C:\Ruby193\bin\test\New Text Document.txt"
становитсяC:\Ruby193\bin\test\NEWTEX~1.TXT
в качестве аргумента.
Нет проблем при запуске скрипта из командной строки с длинными именами файлов в качестве параметров.
Как я могу получить длинное имя файла, когда я использую перетаскивание или отправить?
4 ответа
Я не знаю, возможно ли изменить аргумент, который вы получаете при перетаскивании, но вы могли бы использовать Win32 getLongPathName()
функция, использующая привязки Ruby Win32
--редактировать--
Включая решение @peter, отформатированное для удобства чтения:
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|
puts a
puts get_long_win32_filename(a)
end
http://www.varioustopics.com/ruby/518646-rre-ruby-cygwin-and-paths.html
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|
puts a
puts get_long_win32_filename(a)
end
Я многому научился, пытаясь понять это!
Тем не менее, @peter обошел меня гораздо более простым решением.
Вот мое, на случай, если кто-то найдет это полезным. file_get_long_name.rb
Я получил идею из: заархивированной статьи vb-world.net и преобразовал ее в ruby.
require 'win32ole'
def get_long_filename(shortpath, fso = WIN32OLE.new("Scripting.FileSystemObject"))
path = case
when fso.FolderExists(shortpath)
fso.GetFolder(fso.GetAbsolutePathName(shortpath))
when fso.FileExists(shortpath)
fso.GetFile(fso.GetAbsolutePathName(shortpath))
else
return nil
end
parts = path.Path.split(/\\/)
working = fso.GetDrive(parts.shift).RootFolder
longpath = working.Path
parts.each do |part|
temppath = fso.BuildPath(longpath, part)
working = fso.GetFolder(longpath)
if fso.FolderExists(temppath)
working.SubFolders.each do |sub|
longpath = fso.BuildPath(longpath, sub.Name) if part== sub.ShortName || part == sub.Name
end
elsif fso.FileExists(temppath)
working.Files.each do |sub|
longpath = fso.BuildPath(longpath, sub.Name) if part== sub.ShortName || part == sub.Name
end
end
end
longpath
end
fso = WIN32OLE.new("Scripting.FileSystemObject")
short = "C:\\DOCUME~1\\jamal\\Desktop\\NEWTEX~1.TXT"
long = get_long_filename(short, fso)
p long
# ==> "C:\\Documents and Settings\\jamal\\Desktop\\New Text Document.txt"
Я нашел причину, по которой мой сценарий получил короткие имена файлов, я сделал исправление реестра, чтобы включить перетаскивание на ruby-сценариях и ярлыках следующим образом.
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\rbfile\ShellEx\DropHandler]
@="{86C86720-42A0-1069-A2E8-08002B30309D}"
[HKEY_CLASSES_ROOT\rbwfile\ShellEx\DropHandler]
@="{86C86720-42A0-1069-A2E8-08002B30309D}"
[HKEY_CLASSES_ROOT\RubyFile\ShellEx\DropHandler]
@="{86C86720-42A0-1069-A2E8-08002B30309D}"
[HKEY_CLASSES_ROOT\RubyWFile\ShellEx\DropHandler]
@="{86C86720-42A0-1069-A2E8-08002B30309D}"
Но это должно быть следующим для длинных имен файлов
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\rbfile\ShellEx\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"
[HKEY_CLASSES_ROOT\rbwfile\ShellEx\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"
[HKEY_CLASSES_ROOT\RubyFile\ShellEx\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"
[HKEY_CLASSES_ROOT\RubyWFile\ShellEx\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"