我正在编写一个名为 grepath
的实用工具,可以在 %PATH%
中查找与模式匹配的可执行文件。
我需要确定路径中给定的文件名是否可执行(重点在于命令行脚本)。
基于“Tell if a file is executable”,我得到了以下代码:
import os
from pywintypes import error
from win32api import FindExecutable, GetLongPathName
def is_executable_win(path):
try:
_, executable = FindExecutable(path)
ext = lambda p: os.path.splitext(p)[1].lower()
if (ext(path) == ext(executable) # reject *.cmd~, *.bat~ cases
and samefile(GetLongPathName(executable), path)):
return True
# path is a document with assoc. check whether it has extension
# from %PATHEXT%
pathexts = os.environ.get('PATHEXT', '').split(os.pathsep)
return any(ext(path) == e.lower() for e in pathexts)
except error:
return None # not an exe or a document with assoc.
samefile
指的是:
try: samefile = os.path.samefile
except AttributeError:
def samefile(path1, path2):
rp = lambda p: os.path.realpath(os.path.normcase(p))
return rp(path1) == rp(path2)
在给定的上下文中,如何改进is_executable_win
?Win32 API中的哪些函数可以帮助?
P.S.
- 时间性能不重要
subst
驱动器和UNC、Unicode路径不在考虑范围内- 如果使用 Windows XP 上可用的函数,则 C++ 答案可以接受
示例
notepad.exe
is executable (as a rule)which.py
is executable if it is associated with some executable (e.g., python.exe) and.PY
is in%PATHEXT%
i.e.,'C:\> which'
could start:some\path\python.exe another\path\in\PATH\which.py
somefile.doc
most probably is not executable (when it is associated with Word for example)another_file.txt
is not executable (as a rule)ack.pl
is executable if it is associated with some executable (most probably perl.exe) and.PL
is in%PATHEXT%
(i.e. I can runack
without specifing extension if it is in the path)
def is_executable_win_destructive(path):
#NOTE: it assumes `path` <-> `barename` for the sake of example
barename = os.path.splitext(os.path.basename(path))[0]
p = Popen(barename, stdout=PIPE, stderr=PIPE, shell=True)
stdout, stderr = p.communicate()
return p.poll() != 1 or stdout != '' or stderr != error_message(barename)
error_message()
的内容与语言相关。英文版本如下:
def error_message(barename):
return "'%(barename)s' is not recognized as an internal" \
" or external\r\ncommand, operable program or batch file.\r\n" \
% dict(barename=barename)
如果
is_executable_win_destructive()
返回值为真,则表示该路径指向可执行文件。以下是示例:>>> path = r"c:\docs\somefile.doc"
>>> barename = "somefile"
接下来程序会执行 %COMSPEC%(默认是 cmd.exe):
c:\cwd> cmd.exe /c somefile
如果输出如下所示:
'somefile' 不是内部或外部命令,也不是可运行的程序或批处理文件。那么
path
不是可执行文件,否则它就是(为了举例说明,让我们假设在path
和barename
之间存在一对一的对应关系)。另一个例子:
>>> path = r'c:\bin\grepath.py'
>>> barename = 'grepath'
如果
.PY
在%PATHEXT%
中,并且c:\bin
在%PATH%
中,则执行以下操作:c:\docs> grepath
Usage:
grepath.py [options] PATTERN
grepath.py [options] -e PATTERN
grepath.py: error: incorrect number of arguments
上述输出与
error_message(barename)
不相等,因此'c:\bin\grepath.py'
是一个“可执行文件”。那么问题是如何在不实际运行它的情况下找出
path
是否会产生错误?Win32 API函数和用于触发“is not recognized as an internal..”错误的条件是什么?