分类: PERL
2014-02-11 15:33:20
Perl 对文件的操作
1. 复制,移动,重命名
文件系统经常会对文件进行复制和移动,Perl的 File:: Copy 模块可以提供方便的,跨平台的操作:
$old_file=”f:/perlex/001.pl”;
$new_file=”f:/perlex/002.pl”;
copy($old_file, $new_file) or die "Failed to copy: $!";复制文件
copy($old_file, \*STDOUT) or die "Failed to copy: $!";
#该操作可以将文件的内容输出到屏幕
move($old_file, $new_file) or die "Failed to move: $!";
#移动文件,可实现重命名的功能
Perl 还有内建的重命名函数rename。
rename($old_file, $new_file) or die "Failed to rename: $!";
该命令比较依赖操作系统,在大多数情况下 File::Copy 下面的move指令更具有可移植性和可靠性.
对于文件的删除,perl也有一个内建命令unlink,
unlink $file or die "Failed to remove $file: $!";
unlink可以删除多个文件,并返回成功删除文件的个数。但并不建议这么做。因为如果这样做的话,当文件未被删除成功的话,你不知道未被删除的是哪个文件。所以建议一次只删除一个文件
另外需要注意的是,unlink并不能够删除目录。
Perl有一些用于测试文件的操作符,在命令行中输入perl –f –x 可以列出所有这些操作符。
if( -r $file ) {
print "$file is readable.\n";
}
if( -e $file ) {
print "$file exists.\n";
}
另外,stat函数也会一次性的返回文件的大量信息
2 .Perl对目录的操作
如果需要读取目录下面的文件,可以使用opendir和相关的函数readdir。该方法返回的文件列表是按照文件系统中文件的顺序,而没有另外的排序。
opendir( HOMEDIR, $ENV{HOME} ) or die "Failed to read $ENV{HOME}: $!";
my @files = readdir(HOMEDIR);
closedir(HOMEDIR);
# 新的perl版本 (5.6.1 以上) 支持变量作为句柄
opendir( my $home, $ENV{HOME} ) or die "Failed to read $ENV{HOME}: $!";
my @files = readdir($home);
closedir($home);
# 当我们获得了文件的名字后,我们可以对这些文件进行操作
foreach my $file ( @files ) { print "$file\n"; }
Alternately, we can use glob.
my @files = glob("*.txt"); # 以。Txt结尾的文件
# or less commonly:
my @files = <*.txt>;
glob的运行速度是相对较慢的,它返回的文件列表按照ascII排序。
注:以上对目录中文件的获取,子目录被当做文件处理。当我们希望忽略子目录时,可采取以下的方法:
opendir( my $home, $ENV{HOME} ) or die "Failed to read $ENV{HOME}: $!";
foreach my $file ( readdir($home) ) {
next unless -f $file;
# process file
}
创建和移动目录
mkdir $new_dir or die "Failed to make $new_dir $!";
mkdir $new_dir, $mask or die "Failed to make $new_dir: $!";
rmdir $new_dir or die "Failed to remove $new_dir: $!";
对于函数mkdir,如果不带第二个参数测其默认为0777;
对于函数rmdir,如果目录不为空,则函数执行失败。
如果需要创建和移动目录树,我们可以使用Use::Path,
use File::Path;
mkpath( ’shop/inventory/shelf’ );
mkpath( ’shop/inventory/shelf’, 0, $mode );
rmtree( ’shop/inventory/shelf’ );
mkpath 会将成功建立的目录返回,rmtree 则会删除目录及文件,并返回删除的文件的个数。
目录的路径
不同的系统可能对于目录采用不同的分隔符,这大大减低了代码的可移植性。这个时候我们可以使用File::Spec模块。
use File::Spec;
my $dir = File::Spec->catfile( ’shop’, ’inventory’, ’shelf’, ’price.txt’ );
print $dir;
my ($volume,$directories,$file) = File::Spec->splitpath( $dir );
程序的输出如下:
shop/inventory/shelf/price.txt #Unix和类似系统
shop\inventory\shelf\price.txt;# Win32 操作系统
shop:inventory:shelf:price.txt;#Mac OS 9.
对目录的操作,我们可以用函数opendir和readdir来进行,但是我们也有更简便和更显得大气的方法,用标准模块File::Find
use File::Find;
my $YEAR = 365; # 一年中的天数
my $SIZE = 100_000; # 100k 字节
# 需要在命令行中传递路径
foreach my $dir (@ARGV) {
find ( \&find_old_music, $dir );
}
# 那些已经有一年没有听过的音乐,如果大小大于100K的话,列出来
sub find_old_music {
if( /(\.(mp3|ogg)$/i and -A > $YEAR and -s > $SIZE) {
print "$File::Find::name\n";
}
}
当find_old_music 子函数被调用时,它有三个变量需要设置:
$_
设置成为当前文件的名字
$File::Find::dir
设置为当前目录
$File::Find::name
文件的全名,. 相当于 $file::Find::dir/$_.
File::Find 会自动将工作目录改变到当前测试的目录下边
如果你觉得上述的方法不容易理解,那么perl提供了另外一种方法File::Find::Rule
use File::Find::Rule;
my $YEAR_AGO = time() - 365 * 24 * 60 * 60; # Year ago in secs
my $SIZE = 100_000; # 100k bytes
my @old_music = File::Find::Rule->file()
->name ( ’*.mp3’, ’*.ogg’)
->atime( "< $YEAR_AGO" )
->size ( "> $SIZE" )
->in ( @ARGV );
# Do something with @old_music files
atime 返回的是从1970年1月1日开始的以秒计算的时间,