Я пишу 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 и какие условия используются для запуска ошибки "не распознается как внутренняя.."?