Как получить длинное имя файла из 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.

Нет проблем, когда я запускаю сценарий из командной строки с длинными именами файлов в качестве параметров.

Как мне получить длинное имя файла, когда я использую перетаскивание или отправку?


person peter    schedule 14.11.2011    source источник


Ответы (4)


Я не знаю, можно ли изменить аргумент, который вы получаете при перетаскивании, но вы можете использовать Win32 _ 1_, используя функцию Привязки Ruby Win32

--edit--
Включая решение @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
person AShelly    schedule 15.11.2011
comment
Нашел его на varoustopics.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)? длинное_имя [0..lfn_size-1]: короткое_имя end ARGV.each do | a | помещает конец put get_long_win32_filename (a) - person peter; 16.11.2011

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
person peter    schedule 15.11.2011

Я многому научился, пытаясь понять это!

Однако @peter превзошел меня, предложив гораздо более простое решение.

Вот мой, на случай, если кому-то это пригодится. file_get_long_name.rb

Я получил идею из: заархивированного vb -world.net и преобразовал ее в рубиновый.

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"
person zemoxian    schedule 16.11.2011

Я нашел причину, по которой мой скрипт получил короткие имена файлов, я сделал патч реестра, чтобы включить перетаскивание в скриптах ruby ​​и schortcuts следующим образом

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}"
person peter    schedule 09.11.2012