tag section script samp bootstrap 3school ruby unix path

section - "Which in ruby": verificando si el programa existe en $ PATH de ruby



wbr tag in html5 (16)

Use MakeMakefile # find_executable0 con Logging desactivado

Ya hay varias buenas respuestas, pero esto es lo que uso:

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

Esto utiliza el método # find_executable0 indocumentado invocado por MakeMakefile#find_executable para devolver la ruta sin saturar el resultado estándar. El método #which también redirige temporalmente el archivo de registro mkmf a / dev / null para evitar saturar el directorio de trabajo actual con "mkmf.log" o similar.

mis scripts dependen en gran medida de programas y scripts externos. Necesito estar seguro de que existe un programa que necesito llamar. Manualmente, verificaría esto usando ''which'' en la línea de comando.

¿Hay un equivalente a File.exists? para cosas en $PATH ?

(Sí, supongo que podría analizar %x[which scriptINeedToRun] pero eso no es súper elegante.

¡Gracias! yannick

ACTUALIZAR: esta es la solución que conservé:

def command?(command) system("which #{ command} > /dev/null 2>&1") end

ACTUALIZACIÓN 2: Han llegado algunas respuestas nuevas, al menos algunas ofrecen mejores soluciones.

Actualización 3: la gema de ptools ha agregado un método "que" a la clase Archivo.


En Linux utilizo:

exists = `which #{command}`.size.>(0)

Desafortunadamente, which no es un comando POSIX y se comporta de manera diferente en Mac, BSD, etc. (es decir, arroja un error si el comando no se encuentra). Tal vez la solución ideal sería usar

`command -v #{command}`.size.>(0) # fails!: ruby can''t access built-in functions

Pero esto falla porque ruby ​​parece no ser capaz de acceder a funciones incorporadas. Pero el command -v sería la manera POSIX de hacer esto.


Esta es una versión mejorada basada en la respuesta de @ mislav . Esto permitiría cualquier tipo de entrada de ruta y sigue estrictamente cómo cmd.exe elige el archivo para ejecutar en 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


Este es un ajuste de la respuesta de rogeriopvl, por lo que es multiplataforma:

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


Esto es lo que estoy usando. Esta es la plataforma neutral ( File::PATH_SEPARATOR es ":" en Unix y ";" en Windows), solo busca los archivos de programa que en realidad son ejecutables por el usuario efectivo del proceso actual, y termina tan pronto como se encuentra el programa :

## # 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



La verdadera solución multiplataforma funciona correctamente en 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

Esto no utiliza el rastreo del sistema operativo del host, y respeta $ PATHEXT que enumera las extensiones de archivo válidas para ejecutables en Windows.

Desgravación a la which funciona en muchos sistemas, pero no en todos.


Me gustaría agregar eso which toma las banderas -s para el modo silencioso, que solo establece la bandera de éxito, eliminando la necesidad de redirigir la salida.


No es tan elegante, pero funciona :).

def cmdExists?(c) system(c + " > /dev/null") return false if $?.exitstatus == 127 true end

Advertencia : ¡ NO es un consejo recomendado, peligroso !


Puede acceder a las variables de entorno del sistema con el hash ENV:

puts ENV[''PATH'']

Devolverá la RUTA en su sistema. Entonces, si quiere saber si el programa nmap existe, puede hacer esto:

ENV[''PATH''].split('':'').each {|folder| puts File.exists?(folder+''/nmap'')}

Esto se imprimirá true si el archivo fue encontrado o false contrario.


Solución basada en rogeriovl, pero completa la función con la prueba de ejecución en lugar de la prueba de existencia.

def command_exists?(command) ENV[''PATH''].split('':'').each {|folder| File.executable?(File.join(folder, command))} end

Funcionará solo para UNIX (Windows no usa dos puntos como separador)


Tengo esto:

def command?(name) [name, *ENV[''PATH''].split(File::PATH_SEPARATOR).map {|p| File.join(p, name)} ].find {|f| File.executable?(f)} end

funciona tanto para rutas completas como para comandos:

irb(main):043:0> command?("/bin/bash") => "/bin/bash" irb(main):044:0> command?("bash") => "/bin/bash" irb(main):006:0> command?("bush") => nil


Use el método find_executable de mkmf que se incluye en stdlib.

require ''mkmf'' find_executable ''ruby'' #=> "/Users/narkoz/.rvm/rubies/ruby-2.0.0-p0/bin/ruby" find_executable ''which-ruby'' #=> nil


para jruby, cualquiera de las soluciones que dependen de mkmf puede no funcionar, ya que tiene una extensión C.

para jruby, la siguiente es una forma fácil de verificar si algo es ejecutable en la ruta:

main » unix_process = java.lang.Runtime.getRuntime().exec("git status") => #<Java::JavaLang::UNIXProcess:0x64fa1a79> main » unix_process.exitValue() => 0 main »

si el ejecutable no está allí, generará un error de tiempo de ejecución, por lo que es posible que desee hacer esto en un bloque try / catch en su uso real.


##################################################### # 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


def command?(name) `which #{name}` $?.success? end

Inicialmente tomado del hub , que usó el type -t lugar del which aunque (y que falló tanto para zsh como para bash para mí).