How to tell whether a file is executable on Windows in Python?

2024/10/2 16:21:51

I'm writing grepath utility that finds executables in %PATH% that match a pattern. I need to define whether given filename in the path is executable (emphasis is on command line scripts).

Based on "Tell if a file is executable" I've got:

import os
from pywintypes import error
from win32api   import FindExecutable, GetLongPathNamedef 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~ casesand 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.

Where samefile is:

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)

How is_executable_win could be improved in the given context? What functions from Win32 API could help?

P.S.

  • time performance doesn't matter
  • subst drives and UNC, unicode paths are not under consideration
  • C++ answer is OK if it uses functions available on Windows XP

Examples

  • 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 run ack without specifing extension if it is in the path)

What is "executable" in this question

def is_executable_win_destructive(path):#NOTE: it assumes `path` <-> `barename` for the sake of examplebarename = 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)

Where error_message() depends on language. English version is:

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)

If is_executable_win_destructive() returns when it defines whether the path points to an executable for the purpose of this question.

Example:

>>> path = r"c:\docs\somefile.doc"
>>> barename = "somefile"

After that it executes %COMSPEC% (cmd.exe by default):

c:\cwd> cmd.exe /c somefile

If output looks like this:

'somefile' is not recognized as an internal or external
command, operable program or batch file.

Then the path is not an executable else it is (lets assume there is one-to-one correspondence between path and barename for the sake of example).

Another example:

>>> path = r'c:\bin\grepath.py'
>>> barename = 'grepath'

If .PY in %PATHEXT% and c:\bin is in %PATH% then:

c:\docs> grepath
Usage:grepath.py [options] PATTERNgrepath.py [options] -e PATTERNgrepath.py: error: incorrect number of arguments

The above output is not equal to error_message(barename) therefore 'c:\bin\grepath.py' is an "executable".

So the question is how to find out whether the path will produce the error without actually running it? What Win32 API function and what conditions used to trigger the 'is not recognized as an internal..' error?

Answer

shoosh beat me to it :)

If I remember correctly, you should try to read the first 2 characters in the file. If you get back "MZ", you have an exe.


hnd = open(file,"rb")
if hnd.read(2) == "MZ":print "exe"
https://en.xdnf.cn/q/70830.html

Related Q&A

Issue with python/pytz Converting from local timezone to UTC then back

I have a requirement to convert a date from a local time stamp to UTC then back to the local time stamp.Strangely, when converting back to the local from UTC python decides it is PDT instead of the or…

Regex to replace %variables%

Ive been yanking clumps of hair out for 30 minutes doing this one...I have a dictionary, like so:{search: replace,foo: bar}And a string like this:Foo bar %foo% % search %.Id like to replace each var…

Python kivy - how to reduce height of TextInput

I am using kivy to make a very simple gui for an application. Nothing complex, very simple layout.Nevertheless I am having a hard time with TextInputs...They always display with full height and I cant …

Python-Matplotlib boxplot. How to show percentiles 0,10,25,50,75,90 and 100?

I would like to plot an EPSgram (see below) using Python and Matplotlib. The boxplot function only plots quartiles (0, 25, 50, 75, 100). So, how can I add two more boxes?

Python Pandas reads_csv skip first x and last y rows

I think I may be missing something obvious here, but I am new to python and pandas. I am reading a large text file and only want to use rows in range(61,75496). I can skip the first 60 rows withkeyword…

Combine two arrays data using inner join

Ive two data sets in array: arr1 = [[2011-10-10, 1, 1],[2007-08-09, 5, 3],... ]arr2 = [[2011-10-10, 3, 4],[2007-09-05, 1, 1],... ]I want to combine them into one array like this: arr3 = [[2011-10-10, 1…

How to change fontsize of individual legend entries in pyplot?

What Im trying to do is control the fontsize of individual entries in a legend in pyplot. That is, I want the first entry to be one size, and the second entry to be another. This was my attempt at a so…

Split array into equal sized windows [duplicate]

This question already has answers here:Sliding window of M-by-N shape numpy.ndarray(8 answers)Closed 10 months ago.I am trying to split an numpy.array of length 40 into smaller, equal-sized numpy.array…

Is there a way to send a click event to a window in the background in python?

So Im trying to build a bot to automate some actions in a mobile game that Im running on my pc through Bluestacks.My program takes a screenshot of the window, looks for certain button templates in the …

how to store an image into redis using python / PIL

Im using python and the Image module(PIL) to process images.I want to store the raw bits stream of the image object to redis so that others can directly read the images from redis using nginx & htt…