【问题标题】:How to create a symlink on Windows via Ruby?如何通过 Ruby 在 Windows 上创建符号链接?
【发布时间】:2014-02-02 13:51:23
【问题描述】:

在 Ubuntu 上通过 FileUtils.symlink 'X', 'Y' 创建符号链接有效,而在 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 上创建符号链接。

【问题讨论】:

  • 您是否阅读了错误symlink() function is unimplemented on this machine (NotImplementedError)。对于 Windows,它没有实现。
  • 是的,但我希望有人知道通过 Ruby 的解决方法
  • 你不想在这里使用变通方法,最好重构你的代码并避免在 windows 中使用符号链接。
  • @user21033168 我同意了..
  • 另一种方法是创建一个对mklink 进行系统调用的方法,如果平台是window$,将使用该方法

标签: ruby windows


【解决方案1】:

有点尴尬地发布这个丑陋的黑客,但如果你只是要让它工作,你可以重新定义方法和外壳到 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

【讨论】:

    【解决方案2】:

    首先您需要在提升模式下运行脚本: 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
    

    【讨论】:

      【解决方案3】:

      刚刚使用 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')
      

      【讨论】:

        猜你喜欢
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        • 2014-08-06
        • 1970-01-01
        • 1970-01-01
        • 2019-12-07
        • 2015-10-11
        • 2015-01-03
        相关资源
        最近更新 更多