如果你已经在使用find命令,我建议你不要再使用glob。最好直接找到你想要的文件并将它们删除:
use strict;
use warnings;
use File::Find;
use Env qw(HOME);
use constant {
SUFFIX_LIST => qr/\.(log|foo|bar)$/,
DIR_TO_CHECK => $HOME,
};
@file_list;
find ( sub {
return unless -f;
return unless $_ ~= SUFFIX_LIST;
push @file_list, $File::Find::name;
}, DIR_TO_CHECK );
unlink @file_list;
我定义了一个正则表达式(即
qr/.../
),它定义了我感兴趣的后缀列表。我将常量
SUFFIX_LIST
设置为这个正则表达式。如果我的文件名与这个正则表达式匹配,那么这是我想要删除的文件。
我定义了一个
@file_list
,主要是出于习惯和
find
的工作方式。我不是
find
的忠实粉丝,但这就是我们所拥有的。问题在于,
find
希望你把所有的代码都放在
find
子例程中,这是一种
不好的实践。为了解决这个问题,我让我的
find
子例程将我想要的文件推入一个数组中,然后对该数组进行操作。
在这个特定的程序中,由于代码非常简短,我可以直接在
find
中执行
unlink
。然而,大多数情况下,使用这个技巧会更好些。
find
函数使用两个特殊的
包变量,
$File::Find::name
和
$file::Find::dir
。第一个是文件名和完整路径,以给定给
find
命令的目录名开头。第二个是目录名(完整路径)。
find
函数还将
$_
设置为当前文件名。由于
find
实际上在文件所在的目录中,因此
$_
上没有目录名称,并且可以用于测试该文件。
我进行了两个测试:1)这是一个文件吗?2)这个文件的名称是否以我感兴趣的后缀之一结尾。(请注意,对于第一个测试,我可以简单地使用unless -f
,而对于第二个测试,我必须指定$_
变量。)
如果文件是一个文件并且具有正确的后缀,则将其推入我的@file_list
数组中。
我更喜欢将所需的子程序嵌入到我的find
命令中。这样可以使函数与影响它的代码保持在一起。以下两者是等价的:
find ( sub {
return unless -f;
return unless $_ ~= SUFFIX_LIST;
push @file_list, $File::Find::name;
}, DIR_TO_CHECK );
并且
find (\&wanted, DIR_TO_CHECK );
sub wanted {
return unless -f;
return unless $_ ~= SUFFIX_LIST;
push @file_list, $File::Find::name;
};
我在编程中使用常量来表示真正的常数,这是一个好的编程习惯。Perl常量有一些奇怪的地方,它们没有特殊符号。因此,在使用可能与字符串混淆的常量时,必须小心。
我还使用
use Env
来获取我想要定义的环境变量,仅限于这些变量。我可以通过
$ENV{HOME}
结构将它们引入。这取决于你的偏好。
$ENV{..}
结构清楚地表明您正在引入一个环境变量。使用
use Env
更加简洁。