通过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上创建符号链接。

最佳答案

发布这个丑陋的黑客有点尴尬,但如果你只是想让它工作,你可以重新定义方法,并外壳出到mklink。mklink有点复杂,因为它不是一个独立的程序。mklink是一个cmd.exe shell命令。
下面是文件类。对于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

07-26 00:44