On Fri, Sep 21, 2012 at 7:47 AM, Mark Lawrence <breamore...@yahoo.co.uk> wrote:
> On 20/09/2012 22:06, Gelonida N wrote:
>> I'd like to implement the equivalent functionality of the unix command
>> /usr/bin/which
>> The function should work under Linux and under windows.
>> Did anybody already implement such a function.
> Searching found nothing obvious to me :(
>> If not, is there a portable way of splitting the environment variable
>> PATH?
> With os.sep ?
os.sep is the directory separator, but os.pathsep may be what you
want. Between that and os.getenv('path') you can at least get the
directories. Then on Windows, you also need to check out
os.getenv('pathext') and split _that_ on the semicolon, and try each
of those as a file extension. I'm not sure whether or not Windows will
add extensions from pathext if one is given on the command line - for
instance, if typing "foo.exe" will search for "foo.exe.bat" - but the
basics are there.
Alternatively, there may be a Win32 API funct5ion that does this.
Would be worth a look.
On Thu, Sep 20, 2012 at 4:21 PM, Chris Angelico <ros...@gmail.com> wrote:
> os.sep is the directory separator, but os.pathsep may be what you
> want. Between that and os.getenv('path') you can at least get the
> directories. Then on Windows, you also need to check out
> os.getenv('pathext') and split _that_ on the semicolon, and try each
> of those as a file extension. I'm not sure whether or not Windows will
> add extensions from pathext if one is given on the command line - for
> instance, if typing "foo.exe" will search for "foo.exe.bat" - but the
> basics are there.
Easy enough to test:
C:\>echo echo hello! > foo.exe.bat
C:\>foo.exe
hello!
Yup, it does. It looks like it tries it without the extension first, though:
On Fri, Sep 21, 2012 at 8:32 AM, Ian Kelly <ian.g.ke...@gmail.com> wrote:
> On Thu, Sep 20, 2012 at 4:21 PM, Chris Angelico <ros...@gmail.com> wrote:
>> os.sep is the directory separator, but os.pathsep may be what you
>> want. Between that and os.getenv('path') you can at least get the
>> directories. Then on Windows, you also need to check out
>> os.getenv('pathext') and split _that_ on the semicolon, and try each
>> of those as a file extension. I'm not sure whether or not Windows will
>> add extensions from pathext if one is given on the command line - for
>> instance, if typing "foo.exe" will search for "foo.exe.bat" - but the
>> basics are there.
> Easy enough to test:
> C:\>echo echo hello! > foo.exe.bat
> C:\>foo.exe
> hello!
> Yup, it does. It looks like it tries it without the extension first, though:
Well, at least it's consistent. Makes your PATH extremely sensitive,
though, easy for anyone to inject executables into it. But then, you
can already do that by putting them in the current directory, so
that's not really any different.
Jason's solution looks fine apart from the PATHEXT requirement, so if
you know you have the full filename and you don't care if the actual
command interpreter will do exactly the same, that'll do you fine.
Is this something that might want to be a function in the os module?
Particularly so if, as I suspect there might be, there's a Win32 API
function that precisely replicates the behaviour of executable
invocation. A while since I've done much Windows programming but I
think there's a SearchPath function?
> On Fri, Sep 21, 2012 at 7:47 AM, Mark Lawrence <breamore...@yahoo.co.uk> wrote:
>> On 20/09/2012 22:06, Gelonida N wrote:
>>> I'd like to implement the equivalent functionality of the unix command
>>> /usr/bin/which
>>> The function should work under Linux and under windows.
>>> Did anybody already implement such a function.
>> Searching found nothing obvious to me :(
I was afraid so, but wanted to be sure
>>> If not, is there a portable way of splitting the environment variable
>>> PATH?
>> With os.sep ?
> os.sep is the directory separator, but os.pathsep may be what you
> want.
Thanks,
os.pathsep was the missing piece for portably splitting the searchpath
> Between that and os.getenv('path') you can at least get the
> directories. Then on Windows, you also need to check out
> os.getenv('pathext') and split _that_ on the semicolon, and try each
> of those as a file extension. I'm not sure whether or not Windows will
> add extensions from pathext if one is given on the command line - for
> instance, if typing "foo.exe" will search for "foo.exe.bat" - but the
> basics are there.
For what I am doing I can even skip trying the pathexts, the ext is already given, but good to know :-)
> Alternatively, there may be a Win32 API funct5ion that does this.
> Would be worth a look.
Yeah true, but ideally I'd like to avoid platform detection and
just have a generic function.
> fpath, fname = os.path.split(program)
> if fpath:
> if is_exe(program):
> return program
> else:
> for path in os.getenv("PATH").split(os.pathsep):
> exe_file = os.path.join(path, program)
> if is_exe(exe_file):
> return exe_file
> return None
> IIRC, I adapted it from StackOverflow. I know it works on Linux and Mac
> OS X, but not sure about windows (since I don't know if PATH works the
> same way there).
I'll try it, the script looks reasonably portable (using os.pathsep)
to really replicate which I had probably to add os.getenv('pathext')
as Chris mentioned.
However for my current use case this is not necessarily required.
>> fpath, fname = os.path.split(program)
>> if fpath:
>> if is_exe(program):
>> return program
>> else:
>> for path in os.getenv("PATH").split(os.pathsep):
>> exe_file = os.path.join(path, program)
>> if is_exe(exe_file):
>> return exe_file
>> return None
>> IIRC, I adapted it from StackOverflow. I know it works on Linux and Mac
>> OS X, but not sure about windows (since I don't know if PATH works the
>> same way there).
> I'll try it, the script looks reasonably portable (using os.pathsep)
> to really replicate which I had probably to add os.getenv('pathext')
> as Chris mentioned.
> However for my current use case this is not necessarily required.
On Thu, 20 Sep 2012 23:06:46 +0200, Gelonida N wrote:
> I'd like to implement the equivalent functionality of the unix command
> /usr/bin/which
> The function should work under Linux and under windows.
Note that "which" attempts to emulate the behaviour of execvp() etc. The
exec(3) manpage will explain the precise algorithm used (e.g. they skip
files for which the process lacks execute permission).
Also, note that the shell has built-in commands, functions, and aliases in
addition to programs. The "type" built-in command performs a similar
function to "which" but using the shell's semantics. On some systems,
the default configuration may alias "which" to "type".
On Windows, there's a host of different "execute program" interface, all
with subtly different semantics: which extensions they will run, which
extensions can be omitted, which paths are used (e.g. %PATH%, paths
from the registry, current directory).
> fpath, fname = os.path.split(program)
> if fpath:
> if is_exe(program):
> return program
> else:
> for path in os.getenv("PATH").split(os.pathsep):
> exe_file = os.path.join(path, program)
> if is_exe(exe_file):
> return exe_file
> return None
> IIRC, I adapted it from StackOverflow. I know it works on Linux and Mac OS
> X, but not sure about windows (since I don't know if PATH works the same
> way there).
I don't have a Windows machine set up right now, but I believe there are
two more directories to search, besides the ones described in the PATH
variable.
One is the current directory, and the other is the Windows directory
(maybe also the xxx/system32 or something).
They don't have analogues in Linux or Mac, as far as I know.
> I don't have a Windows machine set up right now, but I believe there are
> two more directories to search, besides the ones described in the PATH
> variable.
> One is the current directory, and the other is the Windows directory
> (maybe also the xxx/system32 or something).
Those system directories are in the path by default.
> On Thu, 20 Sep 2012 23:06:46 +0200, Gelonida N wrote:
>> I'd like to implement the equivalent functionality of the unix command
>> /usr/bin/which
>> The function should work under Linux and under windows.
> Note that "which" attempts to emulate the behaviour of execvp() etc. The
> exec(3) manpage will explain the precise algorithm used (e.g. they skip
> files for which the process lacks execute permission).
> Also, note that the shell has built-in commands, functions, and aliases in
> addition to programs. The "type" built-in command performs a similar
> function to "which" but using the shell's semantics. On some systems,
> the default configuration may alias "which" to "type".
> On Windows, there's a host of different "execute program" interface, all
> with subtly different semantics: which extensions they will run, which
> extensions can be omitted, which paths are used (e.g. %PATH%, paths
> from the registry, current directory).
>> fpath, fname = os.path.split(program)
>> if fpath:
>> if is_exe(program):
>> return program
>> else:
>> for path in os.getenv("PATH").split(os.pathsep):
On Posix systems, you need to insert at this point:
>> IIRC, I adapted it from StackOverflow. I know it works on Linux and Mac OS
>> X, but not sure about windows (since I don't know if PATH works the same
>> way there).
> I don't have a Windows machine set up right now, but I believe there are
> two more directories to search, besides the ones described in the PATH
> variable.
> One is the current directory, and the other is the Windows directory
> (maybe also the xxx/system32 or something).
> They don't have analogues in Linux or Mac, as far as I know.
On Posix system (inlcuding Linux and Mac OS X), the current
directory is not searched by default. If there's an empty
string in os.getenv("PATH").split(os.pathsep), then the
current directory will be searched at that point in the part.