通过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上创建符号链接。
稍微尴尬地发布这个丑陋的黑客,但如果你只是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
首先,您需要以提升模式运行脚本: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
刚刚使用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')