29 r"""Find the full path to commands. 31 which(command, path=None, verbose=0, exts=None) 32 Return the full path to the first match of the given command on the 35 whichall(command, path=None, verbose=0, exts=None) 36 Return a list of full paths to all matches of the given command on 39 whichgen(command, path=None, verbose=0, exts=None) 40 Return a generator which will yield full paths to all matches of the 41 given command on the path. 43 By default the PATH environment variable is searched (as well as, on 44 Windows, the AppPaths key in the registry), but a specific 'path' list 45 to search may be specified as well. On Windows, the PATHEXT environment 46 variable is applied as appropriate. 48 If "verbose" is true then a tuple of the form 49 (<fullpath>, <matched-where-description>) 50 is returned for each match. The latter element is a textual description 51 of where the match was found. For example: 53 from HKLM\SOFTWARE\...\perl.exe 56 from __future__
import unicode_literals
59 Show the full path of commands. 62 which [<options>...] [<command-name>...] 65 -h, --help Print this help and exit. 66 -V, --version Print the version info and exit. 68 -a, --all Print *all* matching paths. 69 -v, --verbose Print out how matches were located and 70 show near misses on stderr. 71 -q, --quiet Just print out matches. I.e., do not print out 74 -p <altpath>, --path=<altpath> 75 An alternative path (list of directories) may 76 be specified for searching. 77 -e <exts>, --exts=<exts> 78 Specify a list of extensions to consider instead 79 of the usual list (';'-separate list, Windows 82 Show the full path to the program that would be run for each given 83 command name, if any. Which, like GNU's which, returns the number of 84 failed arguments, or -1 when no <command-name> was given. 86 Near misses include duplicates, non-regular files and (on Un*x) 87 files without executable access. 90 __revision__ =
"Id: which.py 1448 2007-02-28 19:13:06Z trentm" 91 __version_info__ = (1, 1, 3)
92 __version__ =
'.'.
join(map(str, __version_info__))
93 __all__ = [
"which",
"whichall",
"whichgen",
"WhichError"]
110 def _getRegisteredExecutable(exeName):
111 """Windows allow application paths to be registered in the registry.""" 113 if sys.platform.startswith(
'win'):
114 if os.path.splitext(exeName)[1].lower() !=
'.exe':
118 key =
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" +\
120 value = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, key)
121 registered = (value,
"from HKLM\\"+key)
122 except _winreg.error:
124 if registered
and not os.path.exists(registered[0]):
128 def _samefile(fname1, fname2):
129 if sys.platform.startswith(
'win'):
130 return ( os.path.normpath(os.path.normcase(fname1)) ==\
131 os.path.normpath(os.path.normcase(fname2)) )
133 return os.path.samefile(fname1, fname2)
135 def _cull(potential, matches, verbose=0):
136 """Cull inappropriate matches. Possible reasons: 137 - a duplicate of a previous match 139 - not executable (non-Windows) 140 If 'potential' is approved it is returned and added to 'matches'. 141 Otherwise, None is returned. 143 for match
in matches:
144 if _samefile(potential[0], match[0]):
146 sys.stderr.write(
"duplicate: %s (%s)\n" % potential)
149 if not stat.S_ISREG(os.stat(potential[0]).st_mode):
151 sys.stderr.write(
"not a regular file: %s (%s)\n" % potential)
152 elif sys.platform !=
"win32" \
153 and not os.access(potential[0], os.X_OK):
155 sys.stderr.write(
"no executable access: %s (%s)\n"\
158 matches.append(potential)
164 def whichgen(command, path=None, verbose=0, exts=None):
165 """Return a generator of full paths to the given command. 167 "command" is a the name of the executable to search for. 168 "path" is an optional alternate path list to search. The default it 169 to use the PATH environment variable. 170 "verbose", if true, will cause a 2-tuple to be returned for each 171 match. The second element is a textual description of where the 173 "exts" optionally allows one to specify a list of extensions to use 174 instead of the standard list for this system. This can 175 effectively be used as an optimization to, for example, avoid 176 stat's of "foo.vbs" when searching for "foo" and you know it is 177 not a VisualBasic script but ".vbs" is on PATHEXT. This option 178 is only supported on Windows. 180 This method returns a generator which yields either full paths to 181 the given command or, if verbose, tuples of the form (<path to 182 command>, <where path found>). 187 path = os.environ.get(
"PATH",
"").
split(os.pathsep)
188 if sys.platform.startswith(
"win"):
189 path.insert(0, os.curdir)
194 if sys.platform.startswith(
"win"):
196 exts = os.environ.get(
"PATHEXT",
"").
split(os.pathsep)
200 if ext.lower() ==
".exe":
203 exts = [
'.CMD',
'.COM',
'.EXE',
'.BAT']
204 elif not isinstance(exts, list):
205 raise TypeError(
"'exts' argument must be a list or None")
208 raise WhichError(
"'exts' argument is not supported on "\
209 "platform '%s'" % sys.platform)
214 if os.sep
in command
or os.altsep
and os.altsep
in command:
215 if os.path.exists(command):
216 match = _cull((command,
"explicit path given"), matches, verbose)
223 for i
in range(len(path)):
226 if sys.platform.startswith(
"win")
and len(dirName) >= 2\
227 and dirName[0] ==
'"' and dirName[-1] ==
'"':
228 dirName = dirName[1:-1]
229 for ext
in [
'']+exts:
230 absName = os.path.abspath(
231 os.path.normpath(os.path.join(dirName, command+ext)))
232 if os.path.isfile(absName):
234 fromWhere =
"from given path element %d" % i
235 elif not sys.platform.startswith(
"win"):
236 fromWhere =
"from PATH element %d" % i
238 fromWhere =
"from current directory" 240 fromWhere =
"from PATH element %d" % (i-1)
241 match = _cull((absName, fromWhere), matches, verbose)
247 match = _getRegisteredExecutable(command)
248 if match
is not None:
249 match = _cull(match, matches, verbose)
257 def which(command, path=None, verbose=0, exts=None):
258 """Return the full path to the first match of the given command on 261 "command" is a the name of the executable to search for. 262 "path" is an optional alternate path list to search. The default it 263 to use the PATH environment variable. 264 "verbose", if true, will cause a 2-tuple to be returned. The second 265 element is a textual description of where the match was found. 266 "exts" optionally allows one to specify a list of extensions to use 267 instead of the standard list for this system. This can 268 effectively be used as an optimization to, for example, avoid 269 stat's of "foo.vbs" when searching for "foo" and you know it is 270 not a VisualBasic script but ".vbs" is on PATHEXT. This option 271 is only supported on Windows. 273 If no match is found for the command, a WhichError is raised. 276 match = next(
whichgen(command, path, verbose, exts))
277 except StopIteration:
278 raise WhichError(
"Could not find '%s' on the path." % command)
282 def whichall(command, path=None, verbose=0, exts=None):
283 """Return a list of full paths to all matches of the given command 286 "command" is a the name of the executable to search for. 287 "path" is an optional alternate path list to search. The default it 288 to use the PATH environment variable. 289 "verbose", if true, will cause a 2-tuple to be returned for each 290 match. The second element is a textual description of where the 292 "exts" optionally allows one to specify a list of extensions to use 293 instead of the standard list for this system. This can 294 effectively be used as an optimization to, for example, avoid 295 stat's of "foo.vbs" when searching for "foo" and you know it is 296 not a VisualBasic script but ".vbs" is on PATHEXT. This option 297 is only supported on Windows. 299 return list(
whichgen(command, path, verbose, exts) )
311 optlist, args = getopt.getopt(argv[1:],
'haVvqp:e:',
312 [
'help',
'all',
'version',
'verbose',
'quiet',
'path=',
'exts='])
313 except getopt.GetoptError
as msg:
314 sys.stderr.write(
"which: error: %s. Your invocation was: %s\n"\
316 sys.stderr.write(
"Try 'which --help'.\n")
318 for opt, optarg
in optlist:
319 if opt
in (
'-h',
'--help'):
322 elif opt
in (
'-V',
'--version'):
323 print(
"which %s" % __version__)
325 elif opt
in (
'-a',
'--all'):
327 elif opt
in (
'-v',
'--verbose'):
329 elif opt
in (
'-q',
'--quiet'):
331 elif opt
in (
'-p',
'--path'):
333 altpath = optarg.split(os.pathsep)
336 elif opt
in (
'-e',
'--exts'):
338 exts = optarg.split(os.pathsep)
349 for match
in whichgen(arg, path=altpath, verbose=verbose, exts=exts):
351 print(
"%s (%s)" % match)
362 if __name__ ==
"__main__":
363 sys.exit(
main(sys.argv) )
def which(command, path=None, verbose=0, exts=None)
std::string join(const std::string &base, const std::string &path)
Join two paths, e.g., base path and relative path.
void split(const std::string &path, std::string &head, std::string &tail)
Split path into two parts.
def whichgen(command, path=None, verbose=0, exts=None)
def whichall(command, path=None, verbose=0, exts=None)