文件测试操作符及其意义
文件测试操作符 | 意义 |
---|---|
-r | 文件或目录,对目前(有效的)用户或组来说是可读的 |
-w | 文件或目录,对目前(有效的)用户或组来说是可写的 |
-x | 文件或目录,对目前(有效的)用户或组来说是可执行的 |
-o | 文件或目录,由目前(有效的)用户拥有 |
-R | 文件或目录,对实际的用户或组来说是可读的 |
-W | 文件或目录,对实际的用户或组来说是可写的 |
-X | 文件或目录,对实际的用户或组来说是可执行的 |
-O | 文件或目录,对实际的用户拥有 |
-e | 文件或目录,是存在的 |
-z | 文件存在而且没有内容(对目录来说永远为假) |
-s | 文件或目录存在而且有内容(返回值是以字节为单位的文件大小) |
-f | 是普通文件 |
-d | 是目录 |
-l | 是符号链接 |
-S | 是socket类型的文件 |
-p | 是命名管道,也就是先入先出(fifo)队列 |
-b | 是块设备文件(比如某个可挂载的磁盘) |
-c | 是字符设备文件(比如某个I/O设备) |
-u | 文件或目录设置了setuid位 |
-g | 文件或目录设置了setgid位 |
-k | 文件或目录设置了sticky位 |
-t | 文件句柄是TTY设备(类似系统函数isatty()的测试,不能对文件名进行次测试) |
-T | 看起来像文本文件 |
-B | 看起来像二进制文件 |
-M | 最后一次被修改后至今的天数 |
-A | 最后一次被访问后至今的天数 |
-C | 最后一次文件节点编号(inode)被变更后至今的天数 |
测试同一文件的多项属性
1.写一个程序,从命令行取得一串文件名,并汇报这些文件是否可读,可写,可执行以及是否确实存在.
foreach my $file(ARGV){
my $attribs = &attributes($file);
print "'$file' $attribs.\n";
}
sub attributes{
#报告某个给定的文件的属性
return $file = shift @_;
return "does not exist" unless -e $file;
my @attrib;
push @attrib,"readable" if -r $file;
push @attrib,"writable" if -w $file;
push @attrib,"executable" if -x @file; return "exists" unless @attrib;
'is' .join ' and ', @attrib;
}
2.写一个程序,从命令行参数指定的文件中找出最旧的文件并且以天数汇报它已存在了多久.若列表是空的(也就是命令行中没有提及任何文件),那么它该做什么?
die "No file names supplied!\n" unless @ARGV;
my @oldest_name = shift @ARGV;
my $oldest_age = -M $oldest_name;
foreach(@ARGV){
my $age = -M;
(@oldest_name, @oldest_age) = ($_,$age)
if $age > $oldest_age;
}
printf "The oldest file was %s,and it was %.1f days old.\n",$oldest_name, $oldest_age;
}
3.写一个程序,用栈式文件测试操作符列出命令行参数指定的所有文件,看看拥有者是否是你自己,以及它们是否可读,可写.
use 5.010;
say "Looking for my files that area readable and writabled";
die "No files specified!\n" unless @ARGV;
foreach my $file(@ARGV){
sat "$file is readable and writeable" if -o -r -w $file;
}
在目录树中移动
程序运行是会以自己的工作目录(working directory)作为相对路径的起点.也就说,当我们提及fred这个文件时.其实指的是"当前工作目录下的fred".
你可以用chdir来改变当前的工作目录.它和Unix shell的cd命令差不多:
chdir ‘/etc’ or die “cannot chdir to /etc: $!”;
由Perl程序启动的所有进程都会继承Perl程序的工作目录.可是工作目录的更改却无法影响调用Perl程序的进程比如shell.这意味着你没办法写出可以替代shell里的cd命令的Perl程序,因为一旦退出Perl程序,又会回到启动Perl程序时所在的工作目录.
$echo .pm
barney.pm dino.om fred.pm wilma.pm
这里的echo命令其实斌不知道如何展开.pm,因为shell会先把*.pm展开成一些符合条件的文件名然后再交给他处理.这对Perl程序来说也是一样的.
运行程序时,如果只有一个带有文件名通配符的参数shell会先展开该通配模式,再把结果传递给程序,这样,对程序来说,就好比是看到多个参数.
不过有时候在程序内部也可能需要用*.pm之类的模式.我们可以不用花太多力气就把它展开成相匹配的文件名吗?只要用glob操作符就行了:
my @all_files = glob ‘*’;
my @pm_files = glob ‘*.pm’;
这样说来,加入尖括号既表示从文件句柄读取又代表文件通配操作,那Perl又是如何判断取舍的呢?因为合理的文件句柄必须是严格意义上的Perl标识符,所以如果尖括号内满足Perl标识符条件的,就作为文件句柄来读取;否则,它代表的就是文件名通配操作.
目录句柄
若想从目录里取得文件名列表还可以使用目录句柄,目录句柄看起来像文件句柄,使用起来也没多大差别.
my $dir_to_process = '/etc';
opendir my $dh,$dir_to_process or die "Cannot open $dir_to_process: $!";
foreach $file (readdir $dh){
print "one file in $dir_to_process is $file\n";
}
closedir $dh;
替换运算中左边的点号之前有反斜线,而右边却没有.其实这是因为两边的意义不同,左边的部分是正则表达式,右边的则可视为双引号内的字符串.