Re: Check for another program availability
by pryrt (Abbot) on Apr 10, 2021 at 20:52 UTC
|
if there's a core module that already takes care of such tasks
Not core, but I use File::Which. It correctly handles some of the eccentricities of various operating systems, like correctly handling implied extensions like .bat or .exe on Windows systems. With this module, the same line of code which("perl") will correctly find my Strawberry perl.exe on Windows or /usr/bin/perl on Linux.
| [reply] [d/l] [select] |
Re: Check for another program availability
by jwkrahn (Abbot) on Apr 10, 2021 at 21:50 UTC
|
use Env '@PATH';
...
for my $pathdir ( @PATH ) {
...
| [reply] [d/l] |
|
| [reply] |
Re: Check for another program availability
by Tux (Canon) on Apr 11, 2021 at 07:32 UTC
|
The suggested File::Which is probably *the* solution you want.
The suggested File::Spec is probably (very) good to get used to when writing code that should work on all types of OS's.
I want to add that returning the actual path of the tool/program/script/file is a lot more useful than returning 1.
I also want to say that your approach is less than perfect as you do not skip empty $PATH elements and elements that do not exist or are not a directory. This matters a lot if you are dealing with environments where the environment cannot be trusted. I'd suggest (ignoring both mentioned modules):
use List::Util qw( first );
sub available {
my $prog = shift;
first { -x "$_/$prog } grep { m/\S/ && -d } split m/:+/ => $ENV{PA
+TH};
}
Enjoy, Have FUN! H.Merijn
| [reply] [d/l] [select] |
|
| [reply] |
Re: Check for another program availability
by Discipulus (Canon) on Apr 10, 2021 at 20:19 UTC
|
Hello hrcerq,
I see nothing too bad in your approach. For sure is not a portable way. But you can use File::Spec to split on the correct separator and catfile in a more portable way.
Then you can profit of the cpan module File::SearchPath to accomplish the search.
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] [select] |
Re: Check for another program availability
by dasgar (Priest) on Apr 10, 2021 at 22:00 UTC
|
The core module IPC::CMD has a can_run function that appears to do what you want. And it claims to be "platform independent".
| [reply] |
|
| [reply] |
Re: Check for another program availability (Running External Processes on Unix and Windows References)
by eyepopslikeamosquito (Archbishop) on Apr 12, 2021 at 09:57 UTC
|
Robustly running external processes is a tricky and subtle business.
Having laboured for years at the C level on cross-platform Unix/Windows code --
while lovingly studying the collected works of
Mark Russinovich,
Jeffrey Richter and
the legendary W Richard Stevens (who tragically died way too young at 48) --
I am painfully aware of how differently Windows and Unix deal with processes under the covers.
For example, Unix uses signals for IPC while Windows does not and command line parsing is completely different.
Worse, I have no clue about (and no interest in) the subtleties of running external processes on
Dec VMS,
Classic Mac OS,
and other obscure OSes that Perl supports.
Accordingly, to keep my code simpler and easier to test and troubleshoot (while being correct for each OS),
I usually prefer to use separate code paths for Windows and Unix code that runs external commands
(a crude example of this approach can be found in Timing and timing out Unix commands and Re: Timing Windows commands).
I also worry about the correctness of a cross-platform abstraction and especially the difficulty of troubleshooting bugs.
I might add that I've always applauded Perl for allowing me to easily write Unix-specific code and Windows-specific code when I want to.
So, given your reply here, my advice is to write your Perl code that runs external processes to work on Unix only,
test it on Unix only, and clearly document that assumption.
I don't think you need worry about differences between different Unix flavours (e.g. Linux vs AIX),
at least I'm not aware of any gotchas in this area.
Update: BTW, this reply (in a long debate on the history of Windows NT vs Unix)
mentions the real reason why Windows does not have Unix-like signals, and further notes
the vast gulf between Windows CreateProcess and Unix fork/exec.
References Added Later
These two are excellent:
Other references:
See also:
| [reply] [d/l] [select] |
Re: Check for another program availability
by afoken (Chancellor) on Apr 11, 2021 at 09:29 UTC
|
If the program can be found in $ENV{'PATH'} when it is installed, then just trying to execute it will either succeed or fail, no need to search first. See system and exec.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
| [reply] [d/l] |
|
I’ll sometimes do this as an explicit pre-flight check. If so, it’s either because:
-
I use this program deep in the code and I don’t want to have to unroll a bunch of state (or fail and leave a broken mess) if I get halfway through and then find a critical external program is missing.
-
I want to be unusually user-friendly for a Unix program. Seriously, sometimes the failure that results “naturally” is misleading and will leave the user (usually me) scratching their head and having to troubleshoot. I can save them (myself) a bunch of time if I simply tell them (me) what's wrong.
I agree there’s no point to checking for availability on the line before you try to run the program; you might as well just process the error from system or whatever.
– Aaron Preliminary operational tests were inconclusive. (The damn thing blew up.)
| [reply] [d/l] |
Re: Check for another program availability
by hrcerq (Scribe) on Apr 10, 2021 at 21:44 UTC
|
Thank you both for the portability considerations. The program is mostly focused on OpenBSD and some Linux distros, but we never know, right? Surely I'll check these File modules.
| [reply] |
Re: Check for another program availability
by perlfan (Vicar) on Apr 11, 2021 at 21:24 UTC
|
I'd avoid reimplementing how your shell uses $PATH. If this command is being run in a wrapper, it could be as simple as a commandline argument,
$ perl ./my/script.pl $(which myprogram)
If you don't know the name of the program at first, then,
my $full_program = `which $program`;
chomp $full_program;
Note: which will not "find" a program in $PATH for a file where -x is not also true. In other words, which requires the "found" file to have executable permissions by the effective user. So, yeah; don't try to reimplement which. | [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] |
|
> portable
You didn't say it had to be "portable on Windows".
| [reply] |
|
|
|
Re: Check for another program availability
by Anonymous Monk on Apr 11, 2021 at 13:37 UTC
|
Second IPC::Run can_run(), which is in core.
But if you really want to iterate over PATH, core module File::Spec has a path() that returns the components of PATH or the OS equivalent. It handles Windows (split on /;/<code> not <code>/:/) and I believe even VMS (SYS$PATH or something similar, not PATH).
| [reply] [d/l] [select] |
|
| [reply] [d/l] |