用Python在Windows下模仿Linux的|which.exe|程序
2012-04-01 00:00
369 查看
简介
用Python在Windows下模仿Linux的|which.exe|程序。
这个程序会从Windows环境变量|PATH|里列出的所有目录中查找"可执行文件"。
在Linux下|which.exe|通过文件的"可执行"属性来判断文件是否可执行不同。
在Windows下我们通过扩展名来判断。
如果一个文件的扩展名是|.exe|, |.bat|,或者任何在Windows环境变量|PATHEXT|中列出的扩展名(比如我们自己添加的|.py|),则认为这个文件为"可执行文件"。这个定义也符合Windows的CMD对"可执行文件"的定义。
源码
闲话少说,先上源码。实现的具体分析见源码中注释及源码后的分析。
分析
通过|os.environ.get('PATHEXT')|和|os.environ.get('PATH')|分别得到Window环境变量|PATHEXT|和|PATH|的值。 ## 注意,当这些变量在注册表中没有定义时,|os.environ.get|返回的是None而不是空的list。
将这两个值用|split|拆分为多项。|PATHEXT|的每一个项是一个扩展名(包括点)。|PATH|的每一个项是一个目录路径。
通过将每一个目录路径,与函数参数|program|,与每一个扩展名相组合,得到所有可能的可执行文件的路径。 ## 有两个特殊情况应考虑在内,一个是目录为当前目录,一个是函数参数|program|已经包含了扩展名。
再用|os.path.isfile|判断该路径是否是一个存在的文件。
最后将找到的所有路径打印出来。
用法
先将存有源码的文件命名为|aoiwhich.py|。
在命令行运行:
在俺的机器上得到:
在命令行运行:
在俺的机器上得到:
跋
此软件已开源到 http://sourceforge.net/p/aoiwhich/ 。
用Python在Windows下模仿Linux的|which.exe|程序。
这个程序会从Windows环境变量|PATH|里列出的所有目录中查找"可执行文件"。
在Linux下|which.exe|通过文件的"可执行"属性来判断文件是否可执行不同。
在Windows下我们通过扩展名来判断。
如果一个文件的扩展名是|.exe|, |.bat|,或者任何在Windows环境变量|PATHEXT|中列出的扩展名(比如我们自己添加的|.py|),则认为这个文件为"可执行文件"。这个定义也符合Windows的CMD对"可执行文件"的定义。
源码
闲话少说,先上源码。实现的具体分析见源码中注释及源码后的分析。
__doc__ = """ Author: kuiyuyou@gmail.com File: aoiwhich.py """ import sys import os def find_executable(program): """ Given |program| which is the name or path of a program, find a list of executable paths of the program. #// Arguments program: the name or path of a program. No need to include extension. return: a list of executable paths of the program. #// What an "executable" means? An executable means an existing file whose extension is |.exe|, |.bat|, or any other extensions listed in Windows environment variable |PATHEXT|. #// What is the algorithm used to find all the executable paths? Use each of dir paths listed in Windows environment variable |PATH| as parent dir. Use each of extensions listed in Windows environment variable |PATHEXT| as extension. Synthesize all the possible paths by combining each parent dir, the |program| given, and each extension. (Empty parent dir and empty extension are two special cases.) Check if each path synthesized is an existing executable path. """ #// if not isinstance(program, str): raise TypeError(program) #// create a list to store all the executable paths found the_path_s = [] #// get environment variable |PATHEXT|'s value the_PATHEXT = os.environ.get('PATHEXT') ## |os.environ.get| returns either a str or None #// split |the_PATHEXT| into a list of extensions if the_PATHEXT is None: the_ext_s = [] else: the_ext_s = the_PATHEXT.split(os.pathsep) ## |os.pathsep| on Windows is |;| #// change each item in [the_ext_s] into lowercase the_ext_s = [x.lower() for x in the_ext_s] #// add '.exe' to |the_ext_s| if it is NOT in if '.exe' not in the_ext_s: the_ext_s.append('.exe') #// add '.bat' to |the_ext_s| if it is NOT in if '.bat' not in the_ext_s: the_ext_s.append('.bat') ## The reason to add '.exe' and '.bat': ## ## On Windows, files with an extension of '.exe' or '.bat' are considered ## executable, even if '.exe' and '.bat' are not listed in environment ## variable |PATHEXT|. ## ## However, the algorithm below requires that, an "executable" msut have one ## of the extensions in |the_ext_s|. So to ensure that the algorithm can ## always recognize '.exe' and '.bat' files as executable, we add '.exe' and ## '.bat' to |the_ext_s| manually if they are not listed in |PATHEXT|. #// get a tuple version of |the_ext_s| ## becasue |string.endswith| below takes tuple but not list as argument the_ext_s_tuple = tuple(the_ext_s) #// check if |program| given is an executable full path if os.path.isfile(program) and program.endswith(the_ext_s_tuple): the_path_s.append(program) ## do not return immediately here because if |program| is a relative path, ## algorithm below may find its absolute path as well, e.g. ## if |aoiwhich.py| file's parent dir has been added to PATH, then ## in the same dir, run command |aoiwhich.py aoiwhich.py| would find both ## the relative path |aoiwhich.py| as well as an absolute path. #// get the environment variable |PATH|'s value the_PATH = os.environ.get('PATH') ## |os.environ.get| returns either a str or None #// split |the_PATH| into a list of dir paths if the_PATH is None: the_dir_path_s = [] else: the_dir_path_s = the_PATH.split(os.pathsep) ## |os.pathsep| on Windows is |;| #// insert empty dir path to the beginning of the list of dir paths if '' not in the_dir_path_s: the_dir_path_s.insert(0, '') #// get unique dir paths the_dir_path_s_unique = [] for the_dir_path in the_dir_path_s: if the_dir_path not in the_dir_path_s_unique: the_dir_path_s_unique.append(the_dir_path) #// synthesize possible executable paths. #// check whether each of the synthesized executable paths is existing executable path. for the_dir_path in the_dir_path_s_unique: # synthesize a path # use |the_dir_path| as the parent dir # use |program| as the file name (assuming it has included extension) # use no extension the_path_synthesized = os.path.join(the_dir_path, program) # check if the path synthesized is an existing executable path if os.path.isfile(the_path_synthesized) and the_path_synthesized.endswith(the_ext_s_tuple): the_path_s.append(the_path_synthesized) # for the_ext in the_ext_s: # synthesize a path # use |the_dir_path| as the parent dir # use |program| as the file name (assuming it has NOT included extension) # use |the_ext| as the extension the_path_synthesized_plus_ext = the_path_synthesized + the_ext # check if the path synthesized is an existing executable path if os.path.isfile(the_path_synthesized_plus_ext): the_path_s.append(the_path_synthesized_plus_ext) #// make the list items unique the_path_s_unique = [] for the_path in the_path_s: if the_path not in the_path_s_unique: the_path_s_unique.append(the_path) #// return the_path_s_unique if __name__ == '__main__': #// if len(sys.argv) != 2: print('Usage: {} PROGRAM'.format(sys.argv[0])) print('Example: {} {}'.format(sys.argv[0], 'notepad')) sys.exit(0) ## I was using |argparse| module to parse the arguments, which was very ## convenient. However, |argparse| module is available only since python ## version 3.2. So here I simply check the number of arguments given instead. #// the_program = sys.argv[1] #// find paths according to program name given the_path_s = find_executable(the_program) #// has found NO paths, exit if len(the_path_s) == 0: sys.exit(0) #// has found some paths, print print('\n'.join(the_path_s))
分析
通过|os.environ.get('PATHEXT')|和|os.environ.get('PATH')|分别得到Window环境变量|PATHEXT|和|PATH|的值。 ## 注意,当这些变量在注册表中没有定义时,|os.environ.get|返回的是None而不是空的list。
将这两个值用|split|拆分为多项。|PATHEXT|的每一个项是一个扩展名(包括点)。|PATH|的每一个项是一个目录路径。
通过将每一个目录路径,与函数参数|program|,与每一个扩展名相组合,得到所有可能的可执行文件的路径。 ## 有两个特殊情况应考虑在内,一个是目录为当前目录,一个是函数参数|program|已经包含了扩展名。
再用|os.path.isfile|判断该路径是否是一个存在的文件。
最后将找到的所有路径打印出来。
用法
先将存有源码的文件命名为|aoiwhich.py|。
在命令行运行:
python aoiwhich.py notepad
在俺的机器上得到:
C:\Windows\system32\notepad.exe C:\Windows\notepad.exe
在命令行运行:
python aoiwhich.py regedit
在俺的机器上得到:
C:\Windows\system32\regedit.exe C:\Windows\regedit.exe
跋
此软件已开源到 http://sourceforge.net/p/aoiwhich/ 。
相关文章推荐
- Python脚本转换成windows的exe可执行程序
- python编写简单后门程序(支持windows和linux且不乱码)
- python调用windows的exe可执行程序
- windows下使用cx_freeze将Python程序打包成exe可执行文件
- 如何将python脚本转换成在Windows系统的可执行程序exe
- Python程序windows下打包成exe
- Python 实现根据不同的程序运行环境存放日志目录,Python实现Linux和windows系统日志的存放
- Python学习笔记----把.py程序转化成.exe完美在windows上运行
- 使用 pyinstaller 把python脚本打包成 windows exe 可执行程序
- Windows下用py2exe将Python程序打包成exe程序的教程
- 在Windows下将Python转化成独立的EXE程序 (转载)
- Python写windows service及exe的安装程序
- Py2exe——将python程序变成windows下可执行的exe
- 在linux 上编译生成windows上运行的exe程序,交叉编译环境的配置( 平台:gentoo linux)
- 在WINDOWS上将Python 文件转为(生成)可执行程序 exe 文件
- windows下使用cx_freeze将Python程序打包成exe可执行文件
- Python 一键同步windows和linux数据(基于pscp.exe)
- windows模仿linux下用vim、gcc/g++、 gdb写小程序
- linux下写的程序生成.exe在windows下运行
- 在WINDOWS上将Python 文件转为(生成)可执行程序 exe 文件