Я пишу grepath, которая находит исполняемые файлы в %PATH%, которые соответствуют шаблону.
Мне нужно определить, является ли заданное имя файла в пути исполняемым (акцент делается на скриптах командной строки).
На основе "Скажите, является ли файл исполняемым" У меня есть:
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
Примеры
-
notepad.exeявляется исполняемым (как правило) -
which.pyявляется исполняемым, если он связан с некоторым исполняемым файлом (например, python.exe) и.PYнаходится в%PATHEXT%, т.е.'C:\> which'может начинаться:some\path\python.exe another\path\in\PATH\which.py -
somefile.docскорее всего, не является исполняемым (когда он связан с Word, например) -
another_file.txtне является исполняемым (как правило) -
ack.plявляется исполняемым, если он связан с некоторым исполняемым файлом (скорее всего perl.exe) и.PLнаходится в%PATHEXT%(т.е. я могу запуститьackбез указания расширения, если он находится в пути)
Что такое "исполняемый файл" в этом вопросе
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' is not recognized as an internal or external command, operable program or batch file.
Тогда 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 и какие условия используются для запуска ошибки "не распознается как внутренняя.."?