Morinar
Morinar

Reputation: 3550

Best way to run external app only if it exists

I've got a Perl script that as one of its final steps creates a compressed version of a file it has created. Due to some unfortunate setups, we cannot guarantee that a given customer will have a specific compression function. I want to put something like this together:

if ($has_jar) {
    system("jar -c $compressed_file $infile");
}
elsif ($has_zip) {
    system("zip -j $compressed_file $infile");
}
else {
    copy($infile, $compressed_file);
}

Where if they don't have either of the compression apps, it will just copy the file into the location of the compressed file without compressing it.

My sticky wicket here is that I'm not quite sure what the best way is to determine if they have jar or zip. It looks like I can used exec() instead of system() and take advantage of the fact that it only returns if it fails, but the script actually does do a couple of things after this, so that wouldn't work.

I also need this to be a portable solution as this script runs on both Windows and various Unix distros. Thanks in advance.

Upvotes: 2

Views: 327

Answers (8)

brian d foy
brian d foy

Reputation: 132812

There are a couple of things to think about if you are going to do this:

  • Use system and exec in the list form so the shell doesn't get a chance to interpret special characters.

  • Can you store this as configuration instead of putting it in the code? See how CPAN.pm does it, for instance.

  • How do you know that you are running what you think you are running? If someone makes a trojan horse of the same name, is your program going to happily execute it? Note that using the PATH, as noted in Sinan's multi-which, still has this problem since it relies on the user setting the PATH.

Upvotes: 1

Sinan Ünür
Sinan Ünür

Reputation: 118128

See my multi-which.

Upvotes: 2

For *nix based systems, this should work:

my $has_jar = `which jar` ne '';

This could potentially work for Windows as well if you include which.

Alternatively, you could try the command suggested by this answer,

my $has_jar = `for %i in (jar.exe) do @echo.   %~$PATH:i` ne '';

It most likely doesn't return '' if it doesn't find it, however, but I don't have Perl available on a Windows machine to test it out.

Upvotes: 2

innaM
innaM

Reputation: 47829

I think your best bet is File::Which.

Upvotes: 4

Rob K
Rob K

Reputation: 8926

Why not use the Archive::Zip package to do the compression, eliminating the need for an external program altogether?

Upvotes: 1

John Saunders
John Saunders

Reputation: 161773

How about just try to run the program. If it can't be run, then you know there's a problem.

Upvotes: 1

Aaron Digulla
Aaron Digulla

Reputation: 328604

Usually, things like that don't suddenly disappear from the system, so I suggest to check the presence of the tools during setup/installation and save the one to use in the config.

Upvotes: 1

Paul Nathan
Paul Nathan

Reputation: 40309

Look through the directories specified by the PATH environment variable.

Upvotes: 1

Related Questions