Unable to execute perl script in cmd without invoking perl.exe - perl

I am trying to execute a perl script to delete file1.txt in a directory.
When I execute the perl script using command prompt, I faced an error : Use of uninitialized value in chdir at C:/Debug/test.pl line 7.
Example:
C:\Debug>test.pl C:\Debug
However if I invoke perl in front of test.pl, the perl script is executed successfully and file1.txt was deleted.
Example:
C:\Debug>perl test.pl C:\Debug
Please find test.pl code as follow:
use strict;
use warnings;
use File::Copy;
my ($working_dir) = #ARGV;
chdir $working_dir or die "Can't change directory$!";
unlink "file1.txt";
I have mks_toolkit v8.7.5 with perl.exe installed. The .pl extension is associated with "C:\Program Files (x86)\MKS Toolkit\mksnt\perl.exe" "%1" %*.
I have no problem execute hello.pl (Hello World) without invoking perl in front of it.
Example:
C:\Debug>hello.pl

Anyway, users who face this problem can try to check the properties of your file, make sure the file is not read only and has full admin access.

Related

Execute a perl script which doesnt have the .pl extension from another perl script which have the .pl extension

How to execute a perl script with a file named "first" (no extension) from another perl script called second.pl on Windows?
File contents of first:
#!/usr/bin/perl5.8.4 -w
>> Some code
File contents of second.pl:
#!/usr/bin/perl
use strict;
use warnings;
system "first";
So my problem is when I execute the file "first" from the Windows command line, it works
but if I try to run it from my file "second.pl", using system "first";
it fails with the below error:
can't exec "first" : Not a directory at "second.pl" at line 6
Windows uses the file extension to work out how to run a file. As you have no extension the OS is thinking you are trying to open a directory.
You can fix this by changing system "first"; to
system $^X, "first"
This will get Windows to run the current Perl interpreter again, passing your script name as the first parameter, which gets Perl to run it.

SCALAR output after creating executable from perl script

I have a working perl script that I want to create an executable from. I used PAR::Packer and
pp -o try.exe run_scenarios_1.1.pl
to create the .exe file. Now, when I run the .exe in cygwin with
User#PC ~/my_perls
$ ./try.exe
I get the following output and the program cancels:
User#PC ~/my_perls
$ ./try.exe
SCALAR(0x60103eac8)
Here is my minimal code:
#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
my $export_complete_path = "C:/Prog/Cygwin/home/User/my_perls/test/";
my #test_file = read_file($export_complete_path."Do_Test.txt");
my #combined_data = read_file($export_complete_path."Do_Test_Copy.txt");
### Take the original file and add the current test data
push (#combined_data, #test_file);
### add data to file
open my $newfile, '>', $export_complete_path."combined.txt" or die "\nError: Unable to create in $export_complete_path\n";
write_file($newfile, #combined_data);
It's my first bigger perl program and the first time I use the PAR::Packer.
Do I need to force the packer to do something special?
Thanks in advance :)

execute shell commands from perl script

I want to rename *.DIF files to *.SUC files
But the following script is giving "sh: bad substitution" error
I cannot use "rename" becuase my OS is not Linux.
$com="for i in *.DIF; do mv \$i \${i/DIF/SUC}; done;";
print $com."\n";
print `$com`;
Output :
for i in *.DIF; do mv $i ${i/DIF/SUC}; done;
sh: bad substitution
If you are having problems with Perl's rename, use File::Copy, a platform-independent module for moving and copying files. It is a core module, so it should be already part of your Perl installation.
If the system command works when you enter it in the shell, but not in Perl, the most likely reason is that Perl isn't using the shell you expect. We would need more information about your system to be sure, though.
There's no need to shell out for file operations that you can easily do within Perl.
The following renames all of your .dif extension files as .suc.
use strict;
use warnings;
use File::Copy qw(move);
move($_, s/dif$/suc/r) for glob('*.dif');
be default perl was using sh, instead of bash, which allows {//}
this question helped.
Finally I used :
open my $bash_handle, '| bash' or die "Cannot open bash: $!";
print $bash_handle 'for i in *.SUC; do mv $i ${i/SUC/DIF}; done;';

How do I execute a Perl program on Windows without calling perl on the command-line?

I have written a small script in Perl which I am executing on Windows with ActivePerl as below:
C:\Documents and Settings\Administrator> perl io.pl io.pl
#!/usr/bin/perl
use warnings;
sub test6 {
while (defined($_ = <>)) {
#chomp($_);
print $_;
}
}
test6;
As you can see, the code is similar to the Unix cat command:
C:\Documents and Settings\Administrator> perl io.pl io.pl
If I want to execute this script without the perl keyword on the command line, what needs to be done? I want the script to be executed as:
C:\Documents and Settings\Administrator> ./io.pl io.pl
The .pl extension needs to be associated with the Perl interpreter, for one thing. This is easily done by trying to open the script from Windows Explorer -- when you're asked what program to use to open it, browse to perl.exe. And make sure the "always use this program..." box is checked.
Windows likes to check the current directory first, so you don't need to have the "./" in there.
i think specifying the perl install directory location at the start of the perl script should do it.
#!<perl install directory\bin\perl > rather then #!usr/bin/perl

Perl 'system' failure messages

Say I have this perl "program" called simple.pl:
#!/usr/bin/perl
use xyz; # xyz is bogus and doesn't exist
And I also have this "program", called simple2.pl:
#!/usr/bin/perl
system("simple.pl");
my $abc = `simple.pl`;
printf("abc %s\n", $abc);
for both system and backtick, I get this message:
Can't exec "simple.pl": No such file or directory at scripts/perl/simple2.pl line 7.
Can't exec "simple.pl": No such file or directory at scripts/perl/simple2.pl line 9.
Not very useful for the user calling simple2.pl. Is there a way to get a more useful message?
Note. simple.pl does exist in the current directory. The real problem is that simple.pl doesn't compile. simple2 responds by saying simple doesn't exist. it's a misleading message.
If I had a way to even capture the compile message that would be a start.
This means system couldn't find an executable named "simple.pl" on your PATH. If your simple.pl is in the current directory, you could try to change "simple.pl" to "./simple.pl".
Actually, I don't see how to make this message more descriptive. If you were perl, how would you report this error?
BTW, I wouldn't try to run "simple2.pl" from inside of simple2.pl :)
Yes, check to see if the file exists and is executable, and if it isn't, print a more descriptive message.
unless (-ex $filename) {
print "I am unable to execute file $filename.";
}
If perl say it can't find the file, then it can't find the file. And the problem is more your code. Look at this example.
sidburn#sid:~/perl$ cat test.pl
#!/usr/bin/env perl
use strict;
use warnings;
use xyz;
sidburn#sid:~/perl$ cat test2.pl
#!/usr/bin/env perl
use strict;
use warnings;
system('test.pl');
sidburn#sid:~/perl$ cat test3.pl
#!/usr/bin/env perl
use strict;
use warnings;
system('./test.pl');
If you execute test2.pl you get:
sidburn#sid:~/perl$ ./test2.pl
Can't exec "test.pl": No such file or directory at ./test2.pl line 4.
If you execute test3.pl you get:
sidburn#sid:~/perl$ ./test3.pl
Can't locate xyz.pm in #INC (#INC contains: /home/sidburn/perl510/lib/5.10.1/i686-linux /home/sidburn/perl510/lib/5.10.1 /home/sidburn/perl510/lib/site_perl/5.10.1/i686-linux /home/sidburn/perl510/lib/site_perl/5.10.1 .) at ./test.pl line 4.
BEGIN failed--compilation aborted at ./test.pl line 4.
If you don't provide a relative or absolute path then perl lookup the command in your $PATH environment variable. If it is not there it can't find the file.
You need to provide "./" if it is in the current directory. But note "current directory" doesn't mean the directory where your script relies.
If you want the later then you probably want to do a
use FindBin;
with this you can do something like this:
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use File::Spec::Functions;
my $exe = catfile($FindBin::RealBin, 'test.pl');
print $exe, "\n";
system($exe);
if you want to check if system returns correctly, you need to check the return value from the system() command or $? later that holds the value.
if ( $? != 0 ) {
die "Cannot execute $exe.\n";
}
if you want to suppress messages from your program you need to redirect STDOUT, STDERR before starting your program with system().
Or use something like IPC::System::Simple
Or IPC::Open3 (in the core).
Bonus points for enabling the warnings pragma! Have an upvote!
You want to use backticks or qx// to capture the output of an external program, not system. To substitute your own error message that will make sense to your users (more points for you!), then you might do something as in
#! /usr/bin/perl
use strict;
use warnings;
no warnings 'exec';
chomp(my $abc = `simple2.pl`);
if ($? == 0) {
printf("abc %s\n", $abc);
}
else {
die "$0: unable to calculate abc\n";
}
In case you're unfamiliar, $? is
$CHILD_ERROR
$?
The status returned by the last pipe close, backtick command, successful call to wait or waitpid, or from the system operator.
When $? is zero, it indicates success.
Remember that the warnings pragma is lexical, so rather than disabling the warning for the whole program, you might do it for just one sub:
sub calculate_abc {
no warnings 'exec';
# ...
}
If you are trying to execute something you know is a Perl script, why not invoke the interpreter directly rather than dealing with the system knowing how to execute the file?
my $file = 'simple.pl';
-e $file or die "file '$file' not found";
system "perl $file";
# or
print `perl $file`;
to run with the same installation of perl that is running your current script:
system "$^X $file"; # or `$^X $file`
$^X is a special Perl variable that contains the file name of the running interpreter.
I had the exact same issue and figured out that perl wasn't installed. So the bash script was trying to execute the perl without an interpreter.
ls /usr/bin/perl
Try specifying the full path to the "simple.pl" file.