I'm running script A which feeds ARGV containing the path to a file to perl script B. This is done by a
local @ARGV = ($file, $file2, etc.);
do scriptB.pl or die "scriptB has failed";
Script B then tries to open the file:
open( my $fh_file, "<", $file )
or die "Could not open file '$file' $!";
However, if the file is missing I do not get the message quoted after "or die" in B. Instead I get the do scriptB.pl or die message in A. If I remove the "or die" from A, the script continues after B silently dies as if nothing went wrong.
I was wondering if there was any way to get B to print its die message?
Better yet, what is the best way to have B run a block of code after it fails to open the file? Said code would for example write to a separate file listing which files were missing so that the user may easily track down such errors.
#something like
open( my $fh_file, "<", $file) or {
print "the file could not be found";
die;
}
The only thing I've found searching the net for help was someone mentioning a "or do {}", but this is giving me strange syntax errors so I am not sure if I'm using it right.
Perl open file function You use open() function to open files. The open() function has three arguments: Filehandle that associates with the file. Mode : you can open a file for reading, writing or appending. Filename : the path to the file that is being opened.
Most often, open gets invoked with three arguments: the required FILEHANDLE (usually an empty scalar variable), followed by MODE (usually a literal describing the I/O mode the filehandle will use), and then the filename that the new filehandle will refer to.
If you want to continue to use the open(...) or ...
syntax, then you could use do
.
open my $fh, '<', $file or do {
...
};
But I think it's probably clearer to switch to if
if (! open my $fh, '<', $file) {
...
}
Or even unless
unless (open my $fh '<', $file) {
...
}
I think you'll get clearer code with fewer gotchas if you put script B into a module, and load it with use
or require
and call the function(s) in there directly with clear parameters.
What you're missing here is that do
involves an eval
behind the scenes, and that results in the exception confusion. You can more or less avoid that confusion by moving your script B code into a function in a module, and calling it.
(Also, perl 5.26 will have a slight hiccup with do
wherein the current directory will be removed from the directory lookup, due to security concerns. use
and require
have the same hiccup, but this may be less surprising since you should put your module into a path you explicitly get into the @INC
load path.)
die
doesn't print a message; die
throws an exception. When you catch that exception you don't do anything with the message passed to die
. Replace
local @ARGV = ($file, $file2, etc.);
do scriptB.pl or die "scriptB has failed";
with
local @ARGV = ($file, $file2, etc.);
do scriptB.pl or die "scriptB has failed: ". ( $@ || $! );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With