簡體   English   中英

如何通過Ruby在Windows上創建符號鏈接?

[英]How to create a symlink on Windows via Ruby?

通過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上創建符號鏈接。

有點尷尬地發布這個丑陋的hack,但是如果您只是通過GOTTA使其工作,則可以重新定義方法並將其外殼到mklink。 mklink有點復雜,因為它不是獨立程序。 Mklink是一個cmd.exe Shell命令。

以下是File類。 對於FileUtils,您可以替換文檔中列出的類名並重新定義所需的方法

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

首先,您需要以提升模式運行腳本 :以提升模式運行ruby腳本

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

剛剛測試此使用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')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM