如何通过Ruby在Windows上创建符号链接?

问题描述 投票:1回答:3

通过FileUtils.symlink 'X', 'Y'在Ubuntu上创建符号链接可以在Windows上运行时发生以下错误:

C:/ruby/lib/ruby/2.0.0/fileutils.rb:349:in `symlink': symlink() function is unimplemented on this machine (NotImplementedError)
from C:/ruby/lib/ruby/2.0.0/fileutils.rb:349:in `block in ln_s'
from C:/ruby/lib/ruby/2.0.0/fileutils.rb:1567:in `fu_each_src_dest0'
from C:/ruby/lib/ruby/2.0.0/fileutils.rb:347:in `ln_s'
from C:/test/test.rb:7:in `<class:Test>'
from C:/test/test.rb:1:in `<main>'

作为一种解决方法,可以通过mklink在Windows上创建符号链接,但我也希望通过Ruby在Windows上创建符号链接。

ruby windows
3个回答
4
投票

稍微尴尬地发布这个丑陋的黑客,但如果你只是GOTTA让它工作,你可以重新定义方法和shell到mklink。 mklink有点复杂,因为它不是一个独立的程序。 Mklink是一个cmd.exe shell命令。

下面是File类。对于FileUtils,您可以替换类名称并重新定义所需的方法,如列出的in the docs

require 'open3'

class << File
  alias_method :old_symlink, :symlink
  alias_method :old_symlink?, :symlink?

  def symlink(old_name, new_name)
    #if on windows, call mklink, else self.symlink
    if RUBY_PLATFORM =~ /mswin32|cygwin|mingw|bccwin/
      #windows mklink syntax is reverse of unix ln -s
      #windows mklink is built into cmd.exe
      #vulnerable to command injection, but okay because this is a hack to make a cli tool work.
      stdin, stdout, stderr, wait_thr = Open3.popen3('cmd.exe', "/c mklink #{new_name} #{old_name}")
      wait_thr.value.exitstatus
    else
      self.old_symlink(old_name, new_name)
    end
  end

  def symlink?(file_name)
    #if on windows, call mklink, else self.symlink
    if RUBY_PLATFORM =~ /mswin32|cygwin|mingw|bccwin/
      #vulnerable to command injection because calling with cmd.exe with /c?
      stdin, stdout, stderr, wait_thr = Open3.popen3("cmd.exe /c dir #{file_name} | find \"SYMLINK\"")
      wait_thr.value.exitstatus
    else
      self.old_symlink?(file_name)
    end
  end
end

0
投票

首先,您需要以提升模式运行脚本:Run ruby script in elevated mode

def windows?
  RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
end

if windows?
  def FileUtils.symlink source, dest, out = nil
    dest = File.expand_path(dest).gsub(?/, ?\\)
    source = File.expand_path(source).gsub(?/, ?\\)
    opt = File.directory?(source) ? '/d ' : ''
    output = `cmd.exe /c mklink #{opt}"#{dest}" "#{source}"` # & pause`
    out.puts output if out
  end
end

0
投票

刚刚使用JRuby 9.1.13.0(2.3.3)对此进行了测试,FileUtils现在似乎正在处理Windows符号链接。如果以管理员身份运行,以下操作正常。软链接也应该没有管理员权限。

require 'fileutils'

# Hardlinks work only for files
FileUtils.ln('./dir/file', './link')
# Softlinks to directories are created as symlinkd
FileUtils.ln_s('./dir', './link_dir')
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.