“which in ruby”: Checking if program exists in $PATH from ruby

后端 未结 16 1044
萌比男神i
萌比男神i 2020-12-07 12:15

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

相关标签:
16条回答
  • 2020-12-07 12:39
    #####################################################
    # 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
    
    0 讨论(0)
  • 2020-12-07 12:41

    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.

    0 讨论(0)
  • 2020-12-07 12:42

    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.

    0 讨论(0)
  • 2020-12-07 12:47

    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
    
    0 讨论(0)
  • 2020-12-07 12:48

    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.

    0 讨论(0)
  • 2020-12-07 12:52

    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
    
    0 讨论(0)
提交回复
热议问题