如何覆盖File::Copy::move?
How to override File::Copy::move?
考虑以下简单模块MyCode.pm。它包含一个函数 my_function
,用于处理文件然后重命名。
#!/usr/bin/perl
package MyCode;
use strict;
use warnings;
use IO::File;
use File::Copy;
sub my_function {
# touch /tmp/a
my $fh = IO::File->new();
$fh->open(">/tmp/a") || die "open failed ($!)";
$fh->close() || die "close failed ($!)";
unlink("/tmp/aa"); # ignore errors; we want file removed
move("/tmp/a", "/tmp/aa") || die "move failed ($!)";
}
1;
现在考虑下面的测试程序。它将成功覆盖 IO::File::open
、IO::File::close
但不会覆盖 File::Copy::move
。为什么?
#!/usr/bin/perl -l
use strict;
use warnings;
use IO::File;
use File::Copy;
use MyCode;
{
no warnings 'redefine';
local *IO::File::open = sub {
eval {
$! = 44; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
{
no warnings 'redefine';
local *IO::File::close = sub {
eval {
$! = 33; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
{
no warnings 'redefine';
local *File::Copy::move = sub {
eval {
$! = 22; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
程序输出如下。 move
覆盖没有输出,这意味着它不会启动。为什么?我也想知道为什么我会收到那个警告。
Name "IO::File::close" used only once: possible typo at ./test.pl line 28.
open failed (Channel number out of range) at MyCode.pm line 14.
close failed (Numerical argument out of domain) at MyCode.pm line 15.
使用完整路径 (File::Copy::move) 效果非常好。只需要将 'use' 更改为 'require' 即可在运行时导入。
use strict;
use warnings;
# use File::Copy;
require File::Copy;
use Errno;
{
no warnings 'redefine';
local *move = sub {
eval {
$! = Errno::EREMMO;
die "oops ($!)";
};
};
File::Copy::move("d:\swadhi\perl\a.txt.bak", "D:\swadhi\perl\bakkkkkup.txt") || print $@;
It will successfully override IO::File::open, IO::File::close but not File::Copy::move. Why?
它确实覆盖了 File::Copy::move
。问题是您没有调用 File::Copy::move
,而是调用 MyCode::move
。因此,您需要使用
local *MyCode::move = sub { ... };
I'd like to know also why I am getting [the warning Name "IO::File::close" used only once: possible typo
].
警告的存在是为了帮助查找拼写错误。它在编译过程中只遇到一次包符号时发出。在这种情况下,这是一个虚假警告(就像您禁用的重新定义的警告一样)。
替换
no warnings 'redefine';
和
no warnings 'once';
考虑以下简单模块MyCode.pm。它包含一个函数 my_function
,用于处理文件然后重命名。
#!/usr/bin/perl
package MyCode;
use strict;
use warnings;
use IO::File;
use File::Copy;
sub my_function {
# touch /tmp/a
my $fh = IO::File->new();
$fh->open(">/tmp/a") || die "open failed ($!)";
$fh->close() || die "close failed ($!)";
unlink("/tmp/aa"); # ignore errors; we want file removed
move("/tmp/a", "/tmp/aa") || die "move failed ($!)";
}
1;
现在考虑下面的测试程序。它将成功覆盖 IO::File::open
、IO::File::close
但不会覆盖 File::Copy::move
。为什么?
#!/usr/bin/perl -l
use strict;
use warnings;
use IO::File;
use File::Copy;
use MyCode;
{
no warnings 'redefine';
local *IO::File::open = sub {
eval {
$! = 44; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
{
no warnings 'redefine';
local *IO::File::close = sub {
eval {
$! = 33; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
{
no warnings 'redefine';
local *File::Copy::move = sub {
eval {
$! = 22; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
程序输出如下。 move
覆盖没有输出,这意味着它不会启动。为什么?我也想知道为什么我会收到那个警告。
Name "IO::File::close" used only once: possible typo at ./test.pl line 28.
open failed (Channel number out of range) at MyCode.pm line 14.
close failed (Numerical argument out of domain) at MyCode.pm line 15.
使用完整路径 (File::Copy::move) 效果非常好。只需要将 'use' 更改为 'require' 即可在运行时导入。
use strict;
use warnings;
# use File::Copy;
require File::Copy;
use Errno;
{
no warnings 'redefine';
local *move = sub {
eval {
$! = Errno::EREMMO;
die "oops ($!)";
};
};
File::Copy::move("d:\swadhi\perl\a.txt.bak", "D:\swadhi\perl\bakkkkkup.txt") || print $@;
It will successfully override IO::File::open, IO::File::close but not File::Copy::move. Why?
它确实覆盖了 File::Copy::move
。问题是您没有调用 File::Copy::move
,而是调用 MyCode::move
。因此,您需要使用
local *MyCode::move = sub { ... };
I'd like to know also why I am getting [the warning
Name "IO::File::close" used only once: possible typo
].
警告的存在是为了帮助查找拼写错误。它在编译过程中只遇到一次包符号时发出。在这种情况下,这是一个虚假警告(就像您禁用的重新定义的警告一样)。
替换
no warnings 'redefine';
和
no warnings 'once';