0

I am running perl under Windows 7 x86 and I get an error when I call subroutine which execute external commands from another script.

I have two scripts, script1 has a subroutine that executes a program (patt.exe) and script2 that use this subroutine via require.

When I run script1, it works properly. But when I try to use this subroutine from inside script2, I get the following error.

Error:

'patt.exe' is not recognized as an internal or external command, operable program or batch file.

script1:

#patt('file.txt');
sub patt { 
my $filename=shift@;
system("cmd.exe /c patt.exe -S $filename");
}
1;

script2:

require 'sub-directory/script1.pl';
patt('file.txt');

I should mention that script1 and patt.exe are located in the sub-directory (require 'sub-directory/script1.pl';) and when I put all files in same directory ( require 'script1.pl';) everything works correctly. This problem remains if I use qx or when I pass arguments to the script as array.

I would be very thankful if anyone could help me.

3
  • -f "patt.exe" or die "must be in some other folder"; right before system call Commented Jun 16, 2014 at 12:54
  • @mpapec, When I put both scripts and .exe files in same directory it work correctly. Currently "script1" and "patt.exe" located in the sub_directory and in script2 I mentioned that "require 'sub_directory/script1.pl';". What could possibly be wrong?!. Is there anyway for me to put .exe files with subroutines scripts in separated folder? Commented Jun 16, 2014 at 13:16
  • 3
    This is windows question; use full .exe path or put it in your system PATH. Commented Jun 16, 2014 at 13:21

2 Answers 2

0

One solution is that you can change the current working directory to that of your external program. To do that you can utilize __FILE__ variable of the perl script that shares the same directory as your program.

Of course, one thing to note is that you'll probably need to provide fully qualified paths to your $filename if you go with this solution:

use strict;
use warnings;

use Cwd;
use File::Spec;

sub patt {
    my $filename = shift;

    # Temporarily change cwd
    my $oldcwd = cwd;
    my ($vol, $path) = File::Spec->splitpath(__FILE__);
    chdir($path);

    # Execute program.  Note that $filename will likely need to be a fully qualified path
    system("patt.exe -S $filename");

    # Revert cwd
    chdir($oldcwd);
}

1;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @Miller, Your solution works great. I've replaced my ($vol, $path) = File::Spec->splitpath(__FILE__); with my $path=__FILE__; $path=~ s/\/.+?\.pl//; and all things work well.
0

First of all, you don't need to call pratt.exe via cmd.exe. You should be able to do this:

system "patt.exe -S $filename";

The error is coming from the system command not being able to find the command patt.exe in order to execute it. Try this:

 warn "WARN: \@INC: " . join "\n ", $ENV{PATH};

This will print out all of the directories that Will be searched for the executable. Usually in Windows the current directory is the last entry in $PATH. I'm not 100% sure how require works in relationship to the current working directory. For example, it could be that when you put your subroutine in a file in another directory, it can't find pratt.exe located in the current directory since the current directory is now where the subroutine is located.

So, another thing you might want to do is use the Cwd to import the cad command:

use strict;     # Always! This will help point to errors.
use warnings;   # Always! This will help point to errors.
use Cwd;

sub patt { 
    my $filename = shift;

    warn "Current Working Directory is: " . cwd;
    warn "PATH is: " . join "\n", $ENV{PATH};

    my $error = system("cmd.exe /c patt.exe -S $filename");
    if ( $error ) {
       die qq(Patt failed.);
    }
}
1;

Check the current working directory against the Windows PATH and see if that gives you a hint why patt isn't getting executed.

2 Comments

thanks. Executable file is not in my system path and I don't want (I have not permission in main working PC) to set it. It's clear for me that second script when calls first script, runs all subroutines in its directory, not in script1 sub-directory. At these conditions .exe file must be in script2 directory. I have a lot of .exe file and want to arrange them in sub-directories not main directory.
Then, you'll have to include the directory name of the executable in the system call. Something you could try: Change the $ENV{PATH} variable itself to include the required directories. You can do this on Unix, and it'll hold, but I don't know if this will work on Windows. Append your directories, and see if you can access your executables. On Unix, the PATH is reset after the program exits.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.