I was playing with some python code I have that uses shutil.which(cmd[0])
to try and figure out if the the first argument of a given command would be executable from the current directory.
I passed in the full path of an app (or so I thought) to the code and it didn’t work. I thought about it a bit more and realized I was passing something like: C:\program
instead of C:\program.exe
which was making shutil.which(cmd[0])
returned None.
I don’t think this behavior matches up at least with my expectations. I had expected shutil.which
to test with appending PATHEXT
extensions to return a pseudo-matching executable.
For fun, I tested the same idea with a build of GNU which
for Windows and it matches my expectations:
c:\>which --version
GNU which v2.20, Copyright (C) 1999 - 2008 Carlo Wood.
GNU which comes with ABSOLUTELY NO WARRANTY;
This program is free software; your freedom to use, change
and distribute this program is protected by the GPL.
c:\>which cmd
C:\WINDOWS\system32\cmd.EXE
c:\>which C:\WINDOWS\system32\cmd
C:\WINDOWS\system32\cmd.EXE
c:\>which C:\WINDOWS\system32\cmd.EXE
C:\WINDOWS\system32\cmd.EXE
While Python doesn’t work with passing the non-exe’d full path:
Python 3.11.0 (main, Oct 24 2022, 18:26:48) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import shutil
>>> shutil.which('cmd')
'C:\\WINDOWS\\system32\\cmd.EXE'
>>> shutil.which(r'C:\WINDOWS\system32\cmd')
>>> shutil.which(r'C:\WINDOWS\system32\cmd.EXE')
'C:\\WINDOWS\\system32\\cmd.EXE'
>>>
In both cases, my PATHEXT was:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW
I’d like to put in a vote that we match the behavior of GNU which here, which would have made it so:
>>> shutil.which(r'C:\WINDOWS\system32\cmd')
would have returned
'C:\\WINDOWS\\system32\\cmd.EXE'
Any thoughts or objections? (If no objections, I could even try to PR it ). Thanks folks!