I am not a Windows user, but from googling it looks like where on Windows is closer to locate on Unix (searches the whole filesystem, not only executables).
If PATH environment variable is correctly set on Windows, this should work on any system:
function foo(exec)
for dir in split(ENV["PATH"], @static is_windows() ? ";" : ":")
if isdir(dir) && exec in readdir(dir)
return joinpath(dir, exec)
end
end
return ""
end
This is more or less what which does (you should also check that the file is actually executable)
In order to check if the file is executable by the owner, you can do this:
function foo(exec)
for dir in split(ENV["PATH"], @static is_windows() ? ";" : ":")
if isdir(dir) && exec in readdir(dir)
file = joinpath(dir, exec)
if isfile(file) && (uperm(file) & 0x01 > 0)
return file
end
end
end
return ""
end
I also added the test that the file is a regular file, also directory are executable.
But maybe you want to determine if it’s executable by the current user? Note that which uses -x which doesn’t check if current user can run the program. For example, with both bash and dash, on my system:
$ [ -x /sbin/ifconfig ] && echo "Yes, we can" || echo "No, we can't"
Yes, we can
depending on the program, a -h, --help, -v, or --version flag would usually be safe to try. that doesn’t help you locate it, but can tell you if it’s on the path somewhere and the first one found is runnable.
fair point but I think if you know in advance the exe you want to check it’s a simple and effective way especially if you do as tkelman suggestions and use it with a flag such at -h
BTW
with your script the @static is not necessary
Also oddly enough this check: uperm(file) & 0x01 > 0
fails for exe that I can actually execute on windows
e.g. something as simple as
“cmd.exe” fails with that check since it has permission 06 even thought it is executable
I like your script the following should be more robust
function foo(exec)
if is_windows() && rsplit(exec, '.')[end] != "exe"
exec *= ".exe"
end
for dir in split(ENV["PATH"], is_windows() ? ";" : ":")
if isdir(dir) && exec in readdir(dir)
file = joinpath(dir, exec)
if isfile(file)
if (uperm(file) & 0x01 > 0) || (if is_windows(); uperm(file) == 0x06 end)
return file
end
end
end
end
return ""
end
such a function seems like a good candidate for inclusion in base