Perl笔记:11、目录操作

在目录树中切换

程序运行时会以自己的工作目录作为相对路径的起点。可以使用chdir操作符来改变当前的工作目录,这和shell下的cd命令差不多:
chdir "/etc" or die "can't chdir to /etc:$!";
注意这里我用到了$!变量,由于这是对操作系统的调用,所以发生错误时便会设定标量标量$!的值。如果chdir的返回为假,则表示有问题发生,这时通常需要检查一下$!变量的内容。

如果chdir省略参数则跳到当前的目录,这实际上是没有什么意义的。

文件名通配

一般来说shell会将命令行里的文件名模式展开成所有匹配的文件名。这称之为文件名通配。如,假设将*.pm这个文件名模式交给echo命令,shell会将它展开成名成相匹配的文件列表:

$ echo *.pm
barney.pm dino.pm fred.pm wilma.pm

这里的echo命令不必知道该如何展开*.pm,因为shell会将它展开,再交给echo处理,这也同样适合于perl程序:

#!/usr/bin/perl -w
use strict ;

foreach ( @ ARGV ) {
print "one arg is $_\n" ;
}

$ 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 @all_files = <*>
# 与 my @my_files = glob "*" 一样

my $dir = "/etc" ;
my @dir_files = < $dir /* $dir /.*>;
# $dir变量也会替换为相应的内容

注意:尖括号在perl中即代表了从文件句柄读取,又代表了文件名通配操作,那Perl是如何决定是哪一种的呢?因为合理的文件句柄必须是严格意义上的Perl标识符,所以如果尖括号满足Perl标识符条件的,就作为文件句柄来读取,否则它代表的iushi文件名通配操作。举例来说:

my @files = <FRED /*>; ## glob
my @lines = <FRED> ; ## 从文件句柄读取
my $name = "FRED" ;
my @files = < $name /*>; ## glob
my @lines = < $name >; ## 对句柄FRED进行间接文件句柄读取

目录句柄

若要从目录中取得文件名列表,那就要用到目录句柄,它和文件句柄类似,可以使用opendir打开,readdir读取,closedir关闭,只不多读取的时候是目中的文件名而不是文件的内容,如下例子:
readdir.pl

#!/usr/bin/perl -w
use strict ;

my $dir_to_process = "/etc" ;
opendir DH , $dir_to_process or die "Cannot open $dir_to_process: $!" ;
foreach my $file ( readdir DH ) {
print "one file in $dir_to_process is $file\n" ;
}
closedir DH ;

运行: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

#!/usr/bin/perl -w
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是否执行成功:

my $successful = unlink "slate" , "bedrock" , "lava" ;
print "I deleted $successful file(s) just now\n" ;

重命名文件

使用rename函数来重命名文件,写法: rename "old","new";
下面的例子是将所有的.old文件重命名为.new
rename.pl

foreach my $file ( glob "*.old" ) {
my $newfile = $file ;
$newfile =~ s/\.old$/.new/ ;
if ( -e $newfile ) {
warn "can't rename $file to $newfile: $newfile exists\n" ;
} elsif ( rename $file , $newfile ) {
## 改名成功,什么都不做
} else {
warn "rename $file to $newfile failed: $!\n" ;

--此程序会先检查$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函数转换一下变量,如下:

my $name = "fred" ;
my $permissions = "0755" ;
mkdir $name , oct ( $permissions ) ;

修改权限

chmod 0755, "fred", "barney";
chmod函数与shell下的命令是一致的

更改属主

my $user = 1004 ;
my $group = 100 ;
chown $user , $group , glob "*.o" ;

--如果要处理的不是数字,而是像apache这样的字符串该如何处理呢?很简单,使用getpwnam与getgrnam函数来把用户名或组名转成数字即可,如下:

defined ( my $user = getpwnam "merlyn" ) or die "bad user" ;
defined ( my $group = getgrnam "users" ) or die "bad group" ;
chown $user , $group , glob "/home/merlyn/*" ;

--这里我们使用了defined函数来确认返回值不是undef,也就是说验证指定的用户或组是否真的存在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值