Module: Which

Defined in:
lib/which_works.rb

Overview

The Which module can locate program files in the user’s path. See Which.which.

Class Method Summary collapse

Class Method Details

.which(*programs) ⇒ Object

Locates a program file in the user’s path.

The which method takes a list of command names and searches the path for each executable file that would be run had these commands actually been invoked.

By default, which will return nil if no executable was found, one string if one executable file was found, or an array if several were found. You can customize this behavior by passing the :array option.

Options

  • :all => boolean - List all instances of executables found (instead of just the first one of each). False by default.

  • :array => boolean - Always return an array. False by default.

Examples

Which.which('ls')                  #=> "/bin/ls"
Which.which('unknown')             #=> nil
Which.which('ls', 'screen')        #=> [ "/bin/ls", "/usr/bin/screen" ]
Which.which('svn', :all => true)   #=> [ "/opt/local/bin/svn", "/usr/bin/svn" ]
Which.which('ls', :array => true)  #=> [ "/bin/ls" ]
Which.which('/usr/bin/screen')     #=> "/usr/bin/screen"


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/which_works.rb', line 29

def self.which *programs
  
  found = []
  options = programs.last.kind_of?(Hash) ? programs.pop : {}

  programs.each do |program|

    program_found = false

    # valid file extensions (cross-platform)
    extensions = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [ '' ]

    ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|

      extensions.each do |ext|

        # using expand_path makes it work with absolute program paths
        absolute_path = File.expand_path "#{program}#{ext}", path

        if File.executable? absolute_path
          program_found = true
          found << absolute_path
          break unless options[:all]
        end
      end

      break if program_found && !options[:all]
    end
  end

  if found.length <= 1
    options[:array] ? found : found.first
  else
    found
  end
end