假设在程序里有个包含路径的长文件名,比如/usr/local/bin/perl
,而你希望取出文件的基名(basename)而不包括目录。
my $name = "/usr/local/bin/perl";
(my $basename = $name) =~ s#.*##;
use v5.14;
my $name = "/usr/local/bin/perl";
my $basename = $name =~ s#.*##r;
这样写看起来好像不错,但实际上有安全隐患
/s
修饰符来修正$ perldoc File::Basename # 查看使用说明
use File::Basename;
my $name = "/usr/local/bin/perl";
my $basename = basename $name; # 返回'perl'
这个模块会判断当前所用的操作系统,并且使用该系统默认的文件命名规则
File::Basename
模块还提供了一些其它函数,比如dirname
函数可以从文件全名中取得目录名称,还可以将文件名和扩展名分开,或者是改变默认的文件名规则
程序里现有的子程序名和模块里的某个函数同名
只需在File::Basename
的use声明中加上导入列表来指明要导入的函数清单,就不会自动导入所有函数了
use File::Basename qw/ basename /;
像下面这样写的话说明我们完全不要引入任何函数
use File::Basename qw//;
use File::Basename();
这条指令告诉perl,加载File::Basename
模块,但不要导入任何函数名称。导入函数的目的是要以简短的函数名使用,像basename
和dirname
。不过即使我们不导入这些名称,我们还是可以通过全名的方式来调用相应的函数
use File::Basename qw/ /; # 不导入函数名称
my $betty = &dirname($wilma); # 使用我们自己的子程序&dirname
my $name = "/usr/local/bin/perl";
my $dirname = File::Basename::dirname $name; # 使用模块中的dirname函数
模块里的dirname
函数的全名是File::Basename::dirname
。加载模块后,无论是否导入dirname
这种简短名称,我们都可以随时使用函数全名的方式来调用
大多情况下,使用模块默认导入列表就可以了,大多数模块的默认导入列表里都会省略某些(不常使用的)函数
经常需要把基名和目录名合并形成新的文件全名
use File::Basename;
print "Please enter a filename: ";
chomp(my $old_name = <STDIN>);
my $dirname = dirname $old_name;
my $basename = basename $old_name;
$basename =~ s/^/not/; # 给基名加上前缀
my $new_name = "$dirname/$basename";
rename($old_name, $new_name)
or warn "Can't rename '$old_name' to '$new_name': $!";
这段代码的问题在于,假设文件名遵循unix的惯例
可以利用File::Spec
模块来操作文件说明(file specification),也就是文件名、目录名以及文件系统里的其它名称。它和File::Basename
一样会在运行时判断操作系统的类型,并采用正确规则,但File::Spec
是面向对象的(Object Oriented,OO)模块
use File::Spec;
print "Please enter a filename: ";
chomp(my $old_name = <STDIN>);
my $dirname = dirname $old_name;
my $basename = basename $old_name;
my $new_name = File::Spec -> catfile($dirname, $basename);
rename($old_name, $new_name)
or warn "Can't rename '$old_name' to '$new_name': $!";
调用方法时的全名应该由模块的名称(此处称为类(class))、一个瘦箭头(->)以及方法的简短名称构成。看到瘦箭头,就说明是面向对象的写法,后面是要调用的方法名