I'm using some system commands in Perl.
In the below case I was getting output as follows:
ls: import-log.*: No such file or directory
ls: error-log.*: No such file or directory
No specified files found for开发者_开发百科 deletion
My code:
sub monthoryear()
{
@importlog = `ls -al import-log.*`;
@errorlog = `ls -al error-log.*`;
}
I don't want to see the following in the output even if there are no files.
ls: import-log.*: No such file or directory &
ls: error-log.*: No such file or directory
While the other answers are correct about the exact technical question you asked, you should also consider not writing what is effectively a shell script in Perl.
You should use Perl native methods of getting file list (e.g. glob()
or File::Find
) instead of calling a backticked ls
.
Redirect STDERR to the null device:
use File::Spec;
open STDERR, '>', File::Spec->devnull() or die "could not open STDERR: $!\n";
You can add stderr
redirection in your subshell commands:
@importlog = `ls -al import-log.* 2>/dev/null`;
@errorlog = `ls -al error-log.* 2>/dev/null`;
Check out perlfaq8. If you don't care if it's STDOUT
or STDERR
, you can get both redirected to STDOUT
.
$output = `$cmd 2>&1`;
In your case, you probably just want to get rid of STDERR
:
$output = `$cmd 2>/dev/null`;
However, I agree with DVK's answer. Using an external command to get a list of files just seems silly. You should use File::Find. This way you can use Perl's normal error handling in case something fails.
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my @importlog;
my @errorlog;
find(sub {
push @importlog, $File::Find::name if /^import-log\.*/;
push @errorlog, $File::Find::name if /^error-log\.*/;
}, '.');
print "Import log:\n", join("\n", @importlog), "\n";
print "Error log:\n", join("\n", @errorlog), "\n";
Create a new warn hook, then do something with the message, store it, ignore it etc...
local $SIG{__WARN__} = sub {
my $message = shift;
## do nothing to ignore all together
## ignore specific message
# warn $message unless $message =~ /No such file or directory/;
## or do something else
# die $message ## make fatal
# open my $fh, '>', 'file.log'; print $fh $message;
};
You can redirect the stderr
to /dev/null
as:
@importlog = `ls -al import-log.* 2> /dev/null`;
@errorlog = `ls -al error-log.* 2> /dev/null`;
Subshells will inherit the parent's STDERR, so if you want to do it on a global level, you can do this:
open(STDERR,'>/dev/null');
`ls non-existent-file`;
`ls non-existent-file2`;
`ls non-existent-file3`;
`ls non-existent-file4`;
`ls non-existent-file5`;
Often you also want to restore STDERR
later. I do this like this:
#!/usr/bin/perl
print STDERR "This will be send to the old (readable) STDERR\n";
my $oldstderr = readlink "/proc/self/fd/2"; #Remember the location of the old STDERR
open(STDERR, ">/dev/null"); #Ignore STDERR now
print STDERR "This will be send to a STDERR that is 'gone'\n";
open(STDERR, ">$oldstderr"); #restores STDERR to the old state
print STDERR "This will be send to the old (readable) STDERR again\n";
OR
You can use the Capture::Tiny
module which makes it easier to read and more portable.
#!/usr/bin/perl
use Capture::Tiny qw/capture_stderr/;
print STDERR "This will be send to the old (readable) STDERR\n";
capture_stderr sub {
print STDERR "This will be send to a STDERR that is 'gone'\n";
};
print STDERR "This will be send to the old (readable) STDERR again\n";
Here's how you can suppress STDERR, capture error messages that occur while turned off, restore STDERR, and report back any captured error messages.
#!/usr/bin/perl
use warnings;
use strict;
print STDERR "STDERR is on.\n";
my ($stderr_fh, $err_msg_ref) = suppress_std_err();
print "STDERR is now off and error messages are being suppressed and saved.\n";
print STDERR "I'm an error message.\n";
restore_std_err($stderr_fh);
print STDERR "STDERR is back on\n";
print "Errors reported while STDERR was off: $$err_msg_ref\n";
#Saves STDERR in filehandle then turns it off.
#Any error messages that occur while STDERR is off are stored for safekeeping.
sub suppress_std_err {
my $suppressed_std_error_messages;
open (my $saved_std_err_fh, ">&", STDERR);
close STDERR;
open (STDERR, ">", \$suppressed_std_error_messages);
return ($saved_std_err_fh, \$suppressed_std_error_messages);
}
#Restores STDERR from saved filehandle.
sub restore_std_err {
my $old_std_err_fh = shift;
close STDERR;
open (STDERR, ">&", $old_std_err_fh);
}
精彩评论