在目录树中切换
程序运行时会以自己的工作目录作为相对路径的起点。可以使用chdir操作符来改变当前的工作目录,这和shell下的cd命令差不多:
chdir "/etc" or die "can't chdir to /etc:$!";
注意这里我用到了$!变量,由于这是对操作系统的调用,所以发生错误时便会设定标量标量$!的值。如果chdir的返回为假,则表示有问题发生,这时通常需要检查一下$!变量的内容。
如果chdir省略参数则跳到当前的目录,这实际上是没有什么意义的。
文件名通配
一般来说shell会将命令行里的文件名模式展开成所有匹配的文件名。这称之为文件名通配。如,假设将*.pm这个文件名模式交给echo命令,shell会将它展开成名成相匹配的文件列表:
barney.pm dino.pm fred.pm wilma.pm
这里的echo命令不必知道该如何展开*.pm,因为shell会将它展开,再交给echo处理,这也同样适合于perl程序:
$ perl show-args *.txt
one arg is file.txt
one arg is letter.txt
在这里我上文的程序并不了解如何进行文件通配的处理,放在@ARGV里的已经是展开好了的名称。
有些时候在程序内部,也可能会想要用*.txt之类的模式。我们可以使用glob操作符将它展开成相匹配的文件名:
my @all_files = glob "*";
my @txt_files = glob "*.txt";
--其中@all_files会取得当前目录中的所有文件,并按字母顺序排序,但不包含以点号开头的文件。@txt_files得到所有以.txt结尾的文件。
下面是一次匹配多个模式的例子:
my @all_files_including_dot = glob ".* *";
--其中".*"代表以点开头的文件名,另外注意引号之内两个模式中间的空格是有意的,它分隔了两个要进行文件名通配处理的条目。
文件通配符的另外一种写法
除了上面介绍的glob操作符之外我们可以使用一种简单的方式在perl使用文件通配符,那就是"尖括号写法"(<>):
# 与 my @my_files = glob "*" 一样
my $dir = "/etc" ;
my @dir_files = < $dir /* $dir /.*>;
# $dir变量也会替换为相应的内容
注意:尖括号在perl中即代表了从文件句柄读取,又代表了文件名通配操作,那Perl是如何决定是哪一种的呢?因为合理的文件句柄必须是严格意义上的Perl标识符,所以如果尖括号满足Perl标识符条件的,就作为文件句柄来读取,否则它代表的iushi文件名通配操作。举例来说:
my @lines = <FRED> ; ## 从文件句柄读取
my $name = "FRED" ;
my @files = < $name /*>; ## glob
my @lines = < $name >; ## 对句柄FRED进行间接文件句柄读取
目录句柄
若要从目录中取得文件名列表,那就要用到目录句柄,它和文件句柄类似,可以使用opendir打开,readdir读取,closedir关闭,只不多读取的时候是目中的文件名而不是文件的内容,如下例子:
readdir.pl
运行:perl readdir.pl
one file in /etc is .
one file in /etc is ..
one file in /etc is bashrc
one file in /etc is auto.misc
one file in /etc is firmware
one file in /etc is libaudit.conf
...
one file in /etc is netplug.d
--和文件句柄一样,目录句柄会在程序结束或再用这个句柄打开另一个目录前自动关闭。上面的例子中将. 和..文件都输出了,我现在不想显示这些文件,只想显示*.conf的文件,且按照字母顺序排序,那将如何修改之前的程序呢:
readdir_2.pl
use strict ;
my @file ;
my $dir_to_process = "/etc" ;
opendir DH , $dir_to_process or die "Cannot open $dir_to_process: $!" ;
foreach my $file ( readdir DH ) {
next if $file =~ /^\./ ;
next unless $file =~ /\.conf$/ ;
push @file , "$dir_to_process/$file\n" ;
}
print sort @file ;
closedir DH ;
--这样输出的文件是按照字母顺序且都是.conf的文件
删除文件
使用unlink操作符删除文件:
unlink "slate", "bedrock", "lava";
既然unlink的参数是列表,glob函数又恰好返回列表,我们融合两者可以一次删除多个文件:
unlink glob "*.o";
unlink的返回值是成功删除了多少个文件,下面的例子可以检查unlink是否执行成功:
重命名文件
使用rename函数来重命名文件,写法: rename "old","new";
下面的例子是将所有的.old文件重命名为.new
rename.pl
--此程序会先检查$newfile是否村咋,因为只要用户有删除目标文件的权限rename就会毫不忧郁的覆盖现有的文件。加上这项敬爱奶茶可以减低损失数据的几率
建立和删除目录
mkdir DIRNAME,MASK
mkdir执行后成功返回true失败返回false并设置$!的内容。
[ccie lang="perl"]mkdir "fred", 0755 or warn "Cannot make fred directory: $!";[/cce]
注意:MASK最好不要用变量的形式指定,否则perl会认为这个变量时十进制的数字,而非mkdir认为的八进制,因此,在指定MASK最好使用数字,或者用oct函数转换一下变量,如下:
修改权限
chmod 0755, "fred", "barney";
chmod函数与shell下的命令是一致的
更改属主
--如果要处理的不是数字,而是像apache这样的字符串该如何处理呢?很简单,使用getpwnam与getgrnam函数来把用户名或组名转成数字即可,如下:
--这里我们使用了defined函数来确认返回值不是undef,也就是说验证指定的用户或组是否真的存在。