0

I need to know how to customize my own errors in Perl. For instance, here's some code:

my $filename = 'filaname1.exe';
print "Copying $filename";
copy("$dir_root\\$filename", "$spcl_dir\\$filename");
if ($? == "0") {
    print " - Success!\n";
}
else { print " - Failure!\n"; }

I tried to write this and "catch" the error and print "Failure" when I don't get an exit code of 0, and print "Success" when I do. I need to know how I can customize this; I don't really want to use die or anything like that where it will give a somewhat cryptic error (to the end user).

Thanks!

4
  • 1
    Use /slashes/ not \\\\backslashes\\\\ in /path/names. Commented Nov 26, 2010 at 0:15
  • 1
    If die gives mysterious and unintelligible messages, on your head be it, since you’re who’s passing the cryptic argument to die. You’ve no one else to blame. Commented Nov 26, 2010 at 0:17
  • 1
    Those are terrible error messages. A good error message [1] goes to STDERR [2] includes $0, the name of the program that encountered the error as a minimum, and perhaps the function name; internal errors usually also give a stack trace [3] includes $!, the standard system error message wherever it’s appropriate, or perhaps $? or $@ otherwise [4] states the name of the failed syscall [5] lists the arguments you gave that call. Your message neglects all, or nearly all, of those Five Rules for Good Error Messages. Commented Nov 26, 2010 at 0:21
  • One does not quote numeric literals in Perl. You’re just begging for trouble. Commented Nov 26, 2010 at 0:23

2 Answers 2

4

You need to read the documentation on $? in perlvar. This value is:

The status returned by the last pipe close, backtick ("``") command, successful call to wait() or waitpid(), or from the system() operator.

Your call to copy (presumably from File::Copy) doesn't far into any of those categories, so $? isn't set.

However, if you read the documentation for File::Copy, you'll see that its function all "return 1 on success, 0 on failure". So you can simplify your code a lot.

#!/usr/bin/perl

use strict; use warnings;

use File::Copy;

if (copy('notthere', 'somewhere else')) {
  warn "success\n";
} else {
  warn "failure: $!\n";
}

Note that I've used "warn" rather than "print" so that the errors go to STDERR. Note, also, the use of $! to display the operating system error. This can, of course, be omitted if it's not user-friendly enough.

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

1 Comment

Thanks - this worked great! While djsadinoff's solution will also work, I liked the simplicity of the if statement embedded into the main command, something I'm very familiar with as I am mostly a PHP developer.
1

Are you using File::Copy? You must be using something, because copy() isn't a perl keyword or built-in function.

The documentation of File::Copy doesn't refer to $? at all, so that's probably your mistake. You want to check the return value, and only if it's zero, refer to $!.

use strict;
use File::Copy qw(copy);
my ($from, $to) = @ARGV;
my $res = copy ($from, $to);
if( $res ){
  print "Okay\n";
}
else{
  print "Not Okay: $!\n";
}

1 Comment

Yeah, I'm using File::Copy. I might go with something else (using system(@args), but for now File::Copy is working well.

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.