-
-
Save techtonik/4368898 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
# https://gist.github.com/4368898 | |
# Public domain code by anatoly techtonik <[email protected]> | |
# AKA Linux `which` and Windows `where` | |
# For Python 3 you probably want | |
# https://docs.python.org/dev/library/shutil.html#shutil.which | |
import os | |
import sys | |
def find_executable(executable, path=None): | |
"""Find if 'executable' can be run. Looks for it in 'path' | |
(string that lists directories separated by 'os.pathsep'; | |
defaults to os.environ['PATH']). Checks for all executable | |
extensions. Returns full path or None if no command is found. | |
""" | |
if path is None: | |
path = os.environ['PATH'] | |
paths = path.split(os.pathsep) | |
extlist = [''] | |
if os.name == 'os2': | |
(base, ext) = os.path.splitext(executable) | |
# executable files on OS/2 can have an arbitrary extension, but | |
# .exe is automatically appended if no dot is present in the name | |
if not ext: | |
executable = executable + ".exe" | |
elif sys.platform == 'win32': | |
pathext = os.environ['PATHEXT'].lower().split(os.pathsep) | |
(base, ext) = os.path.splitext(executable) | |
if ext.lower() not in pathext: | |
extlist = pathext | |
# Windows looks for binaries in current dir first | |
paths.insert(0, '') | |
for ext in extlist: | |
execname = executable + ext | |
for p in paths: | |
f = os.path.join(p, execname) | |
if os.path.isfile(f): | |
return f | |
else: | |
return None | |
if __name__ == '__main__': | |
if sys.argv[1:]: | |
print(find_executable(sys.argv[1])) | |
else: | |
print('usage: find_executable.py <progname>') |
You should not automatically check for executable in the current working directory. This makes it too easy for the user to accidentally execute a trojan. Users who really really trust their environment can explicitly add "." to their search PATH if they wish but it is a bad idea.
In short, remove "if os.path.isfile(execname)" and use only the contents of the else block.
As of Python 3.3 there is also shutil.which
.
For python 2 there is from distutils.spawn.find_executable
, the only weirdness is that on windows it will capitalize the extension.
is there any way to make it look in deeper paths? so it would check the whole C DRIVE?
@phdru thanks for the suggestion. Added shebang and command line argument for easy testing with different names.
@KeithHanlan good catch. I was probably writing it from Windows, where it was the default system behavior. There is no point to port this insecurity to Linux.
@KeithHanlan the security issue is now fixed. The old behavior is preserved only for Windows.
@sergio44k you need a standard code for recursive directory search. https://stackoverflow.com/questions/2186525/how-to-use-glob-to-find-files-recursively should help.
@rth
As of Python 3.3 there is alsoshutil.which
.
The most valuable comment for me. The entire solution is just to call shutil.which
.
Added a link to shutil.which
for Python 3 users.
Hi! Can I suggest a patch?