my scripts rely heavily on external programs and scripts. I need to be sure that a program I need to call exists. Manually, I\'d check this using \'which\' in the commandlin
#####################################################
# 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
You can access system environment variables with the ENV hash:
puts ENV['PATH']
It will return the PATH on your system. So if you want to know if program nmap
exists, you can do this:
ENV['PATH'].split(':').each {|folder| puts File.exists?(folder+'/nmap')}
This will print true
if file was found or false
otherwise.
True cross-platform solution, works properly on 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 do |ext|
exe = File.join(path, "#{cmd}#{ext}")
return exe if File.executable?(exe) && !File.directory?(exe)
end
end
nil
end
This doesn't use host OS sniffing, and respects $PATHEXT which lists valid file extensions for executables on Windows.
Shelling out to which
works on many systems but not all.
Here's what I'm using. This is platform neutral (File::PATH_SEPARATOR
is ":"
on Unix and ";"
on Windows), only looks for program files that actually are executable by the effective user of the current process, and terminates as soon as the program is found:
##
# 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
I'd like to add that which
takes the flag -s
for silent mode, which only sets the success flag, removing the need for redirecting the output.
Use find_executable method from mkmf
which is included to stdlib.
require 'mkmf'
find_executable 'ruby'
#=> "/Users/narkoz/.rvm/rubies/ruby-2.0.0-p0/bin/ruby"
find_executable 'which-ruby'
#=> nil