"which in ruby": 프로그램이 ruby에서 $ PATH에 있는지 확인
내 스크립트는 외부 프로그램과 스크립트에 크게 의존합니다. 호출해야하는 프로그램이 있는지 확인해야합니다. 수동으로 명령 줄에서 'which'를 사용하여 확인합니다.
에 대한 것과 동등한 File.exists?
것이 $PATH
있습니까?
(예, 구문 분석 할 수 있다고 생각 %x[which scriptINeedToRun]
하지만 매우 우아하지는 않습니다.
감사! Yannick
업데이트 : 내가 유지 한 솔루션은 다음과 같습니다.
def command?(command)
system("which #{ command} > /dev/null 2>&1")
end
업데이트 2 : 몇 가지 새로운 답변이 나왔습니다. 적어도 이들 중 일부는 더 나은 솔루션을 제공합니다.
업데이트 3 : ptools gem 은 File 클래스에 "which"메소드를 추가했습니다.
진정한 크로스 플랫폼 솔루션은 Windows에서 제대로 작동합니다.
# Cross-platform way of finding an executable in the $PATH.
#
# which('ruby') #=> /usr/bin/ruby
def which(cmd)
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each { |ext|
exe = File.join(path, "#{cmd}#{ext}")
return exe if File.executable?(exe) && !File.directory?(exe)
}
end
return nil
end
이것은 호스트 OS 스니핑을 사용하지 않으며 Windows에서 실행 파일의 유효한 파일 확장자를 나열하는 $ PATHEXT를 존중합니다.
which
많은 시스템 에서 작동하지만 전부는 아닙니다.
stdlib에 포함 된 find_executable
메소드를 사용하십시오 mkmf
.
require 'mkmf'
find_executable 'ruby'
#=> "/Users/narkoz/.rvm/rubies/ruby-2.0.0-p0/bin/ruby"
find_executable 'which-ruby'
#=> nil
def command?(name)
`which #{name}`
$?.success?
end
처음에는 대신 사용 하는 hub 에서 가져 왔습니다 (그리고 나를 위해 zsh와 bash 모두 실패했습니다).type -t
which
로깅이 비활성화 된 상태에서 MakeMakefile # find_executable0 사용
이미 많은 좋은 답변이 있지만 여기에 내가 사용하는 것이 있습니다.
require 'mkmf'
def set_mkmf_log(logfile=File::NULL)
MakeMakefile::Logging.instance_variable_set(:@logfile, logfile)
end
# Return path to cmd as a String, or nil if not found.
def which(cmd)
old_mkmf_log = MakeMakefile::Logging.instance_variable_get(:@logfile)
set_mkmf_log(nil)
path_to_cmd = find_executable0(cmd)
set_mkmf_log(old_mkmf_log)
path_to_cmd
end
이것은 MakeMakefile # find_executable 에 의해 호출 된 문서화되지 않은 # find_executable0 메서드를 사용하여 표준 출력을 복잡하게하지 않고 경로를 반환합니다. #which 메서드는 또한 mkmf 로그 파일을 / dev / null 로 일시적으로 리디렉션 하여 현재 작업 디렉토리가 "mkmf.log"또는 이와 유사한 것으로 복잡 해지는 것을 방지합니다.
ENV 해시를 사용하여 시스템 환경 변수에 액세스 할 수 있습니다.
puts ENV['PATH']
시스템에서 PATH를 반환합니다. 따라서 프로그램 nmap
이 있는지 알고 싶다면 다음 과 같이 할 수 있습니다.
ENV['PATH'].split(':').each {|folder| puts File.exists?(folder+'/nmap')}
true
파일이 발견되거나 false
그렇지 않으면 인쇄 됩니다 .
여기에 제가 사용하고있는 것이 있습니다. 이것은 플랫폼 중립적 File::PATH_SEPARATOR
이며 ( ":"
Unix 및 ";"
Windows에 있음) 현재 프로세스의 유효 사용자가 실제로 실행할 수있는 프로그램 파일 만 찾고 프로그램이 발견되는 즉시 종료됩니다.
##
# Returns +true+ if the +program+ executable is found in the user's path.
def has_program?(program)
ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
File.executable?(File.join(directory, program.to_s))
end
end
which_ruby
순수 Ruby 구현 이라는 GEM이있었습니다 . 더 이상 사용할 수 없습니다.
그러나 나는이 순수한 루비 대체 구현을 발견했습니다 .
성공 플래그 만 설정하는 자동 모드에 which
대한 플래그 -s
를 사용하여 출력을 리디렉션 할 필요가 없도록 추가하고 싶습니다 .
이것은 @mislav의 답변을 기반으로 한 개선 된 버전 입니다. 이것은 모든 유형의 경로 입력을 허용 cmd.exe
하고 Windows에서 실행할 파일을 선택하는 방법을 엄격하게 따릅니다 .
# which(cmd) :: string or nil
#
# Multi-platform implementation of "which".
# It may be used with UNIX-based and DOS-based platforms.
#
# The argument can not only be a simple command name but also a command path
# may it be relative or complete.
#
def which(cmd)
raise ArgumentError.new("Argument not a string: #{cmd.inspect}") unless cmd.is_a?(String)
return nil if cmd.empty?
case RbConfig::CONFIG['host_os']
when /cygwin/
exts = nil
when /dos|mswin|^win|mingw|msys/
pathext = ENV['PATHEXT']
exts = pathext ? pathext.split(';').select{ |e| e[0] == '.' } : ['.com', '.exe', '.bat']
else
exts = nil
end
if cmd[File::SEPARATOR] or (File::ALT_SEPARATOR and cmd[File::ALT_SEPARATOR])
if exts
ext = File.extname(cmd)
if not ext.empty? and exts.any?{ |e| e.casecmp(ext).zero? } \
and File.file?(cmd) and File.executable?(cmd)
return File.absolute_path(cmd)
end
exts.each do |ext|
exe = "#{cmd}#{ext}"
return File.absolute_path(exe) if File.file?(exe) and File.executable?(exe)
end
else
return File.absolute_path(cmd) if File.file?(cmd) and File.executable?(cmd)
end
else
paths = ENV['PATH']
paths = paths ? paths.split(File::PATH_SEPARATOR).select{ |e| File.directory?(e) } : []
if exts
ext = File.extname(cmd)
has_valid_ext = (not ext.empty? and exts.any?{ |e| e.casecmp(ext).zero? })
paths.unshift('.').each do |path|
if has_valid_ext
exe = File.join(path, "#{cmd}")
return File.absolute_path(exe) if File.file?(exe) and File.executable?(exe)
end
exts.each do |ext|
exe = File.join(path, "#{cmd}#{ext}")
return File.absolute_path(exe) if File.file?(exe) and File.executable?(exe)
end
end
else
paths.each do |path|
exe = File.join(path, cmd)
return File.absolute_path(exe) if File.file?(exe) and File.executable?(exe)
end
end
end
nil
end
나는 이것을 가지고있다:
def command?(name)
[name,
*ENV['PATH'].split(File::PATH_SEPARATOR).map {|p| File.join(p, name)}
].find {|f| File.executable?(f)}
end
전체 경로 및 명령에 대해 작동합니다.
irb(main):043:0> command?("/bin/bash")
=> "/bin/bash"
irb(main):044:0> command?("bash")
=> "/bin/bash"
irb(main):006:0> command?("bush")
=> nil
Linux에서는 다음을 사용합니다.
exists = `which #{command}`.size.>(0)
불행히도은 which
POSIX 명령이 아니므로 Mac, BSD 등에서 다르게 작동합니다 (예 : 명령을 찾을 수없는 경우 오류 발생). 아마도 이상적인 해결책은
`command -v #{command}`.size.>(0) # fails!: ruby can't access built-in functions
그러나 이것은 루비가 내장 함수에 접근 할 수없는 것처럼 보이기 때문에 실패합니다. 그러나 command -v
이것을 수행하는 POSIX 방법이 될 것입니다.
Solution based on rogeriovl, but complete function with execution test rather than existence test.
def command_exists?(command)
ENV['PATH'].split(':').each {|folder| File.executable?(File.join(folder, command))}
end
Will work only for UNIX (Windows does not use colon as a separator)
This is a tweak of rogeriopvl's answer, making it cross platform:
require 'rbconfig'
def is_windows?
Config::CONFIG["host_os"] =~ /mswin|mingw/
end
def exists_in_path?(file)
entries = ENV['PATH'].split(is_windows? ? ";" : ":")
entries.any? {|f| File.exists?("#{f}/#{file}")}
end
for jruby, any of the solutions that depend on mkmf
may not work, as it has a C extension.
for jruby, the following is an easy way to check if something is executable on the path:
main » unix_process = java.lang.Runtime.getRuntime().exec("git status")
=> #<Java::JavaLang::UNIXProcess:0x64fa1a79>
main » unix_process.exitValue()
=> 0
main »
if the executable isn't there, it will raise a runtime error, so you may want to do this in a try/catch block in your actual usage.
#####################################################
# add methods to see if there's an executable that's executable
#####################################################
class File
class << self
###########################################
# exists and executable
###########################################
def cmd_executable?(cmd)
!ENV['PATH'].split(':').select { |f| executable?(join(f, cmd[/^[^ \n\r]*/])) }.empty?
end
end
end
Not so much elegant but it works :).
def cmdExists?(c)
system(c + " > /dev/null")
return false if $?.exitstatus == 127
true
end
Warning: This is NOT recommended, dangerous advice!
'Programing' 카테고리의 다른 글
Homebrew Symlink 오류 (0) | 2020.10.18 |
---|---|
Xcode 4.6.3에서 Dropbox API 공동 디자인 실패 : "코드 개체가 전혀 서명되지 않았습니다" (0) | 2020.10.18 |
클릭 할 때 Android에서 버튼의 색상을 변경하는 방법은 무엇입니까? (0) | 2020.10.18 |
결과를 쉼표로 구분 된 목록으로 반환하는 PostgreSQL 쿼리 (0) | 2020.10.18 |
미래를 위해 미세 조정 된 스레드 풀을 구성하는 방법은 무엇입니까? (0) | 2020.10.18 |