6.文件&目录

1.文件

1.1open-close

open FILEHANDLE, EXPR

...
open(FILE,"<sim.log") or die "can't open sim.log,$!";    
#open(FILE,"<","sim.log") or die "can't open sim.log,$!";    #也可以
#open(FILE,"r","sim.log");    #不支持
while(<FILE>){    #<>为钻石操作符,按行读取文件内容
    print "$_\n";
}
close FILE;
#close;    #也可以,但不建议,容易出错

 EXPR中:

<只读(open默认方式),文件指针指向开头;不存在则报错
>只写,文件指针指向开头;不存在则尝试创建
>>只写,文件指针指向结尾(追加);不存在则尝试创建
+<读写,文件指针指向开头,写多少覆盖不少;不存在则报错
+>读写,文件大小直接截为0;不存在则尝试创建
+>>读写,文件指针指向结尾;不存在则尝试创建

*实测sysopen不能创建文件

*open可以重定向,也可以和管道一起使用,略。

1.2读写文件

<> 文件句柄操作符,<FILEHANDLE>读取句柄指向的文件的内容,标量环境返回一行内容,数组环境返回整个文件内容。<>默认从命令行参数列表@ARGV中的文件中读取内容,@ARGV中若无元素,则从STDIN标准输入文件句柄中读取,也可使用<FILEHANDLE>手动指定句柄。

#from @ARGV
@ARGV = ("sim.log");    #@ARGV可以手动修改,如有多个文件,则逐个读取
while(<>){    #标量环境读取一行
    print;
    #print "\n";
}
close;
#from STDIN
while(<>){
    print "$_\n";
}


print FILEHANDLE list,FILEHANDLE默认为STDOUT,即输出到屏幕,也可指定为普通文件句柄。

open DATA,"+>","sim.log" or die "cannot open it,$!";
open DATA1,"<","hello.pl" or die "cannot open it,$!";
print DATA <DATA1>;
=head
数组环境读取整个文件,也可以先赋给一个数组;
读取内容输出到DATA指向的文件中;
print中,DATA后面没有逗号,逗号是连接符;
=cut

#close;  #which FILEHANDLE is closed?强烈不推荐
close DATA1;

=head
fileno:
STDIN, STDOUT和 STDERR 的文件描述符 分别是0,1和 2 (Unix 标准传统),
标准文件输入输出句柄的值从3开始,其具体值由句柄打开的顺序决定。
若某变异 是一个普通变量,则fileno的返回值 是undef;
若某个文件句柄未正常打开或者已关闭,fileno返回的值 也是undef
=cut

print fileno DATA,"\n";    #3 普通文件句柄
print fileno DATA1,"\n";   #undef
print tell DATA,"\n";   #结尾
print tell DATA1,"\n";  #-1,关闭了文件

*rename string1,string2;重命名

*unlink filename1;删除文件

 1.3文件位置

tell FILEHANDLE:获取文件当前位置,以字节计;

seek FILEHANDLE, POSITION, WHENCE:移动读写指针,position指定移动的字节数,whence指定移动的起点,0,1,2分别表示文件开头、当前位置,结尾。

sysopen(DATA,"sim3.log",O_RDONLY) or die "can't open sim.log,$!";

#following sysopen doesn't work
#sysopen(DATA2,"./sim2.log",O_WRONLY|O_CREAT,0755) or die "can't create sim2.log,$!";

open DATA2,"+>sim2.log" or die "can't open sim2.log,$!";
while(<DATA>){
    print DATA2 $_;#there is no "," between DATA2 and $_
    printf "DATA2 position:%d\n",tell DATA2;
    #finally,print moves ptr of DATA2 to the end 
}

print tell DATA2,"\n";
seek DATA2,0,0;    #重定向读写指针到文件开头,否则下面的while无法执行
print tell DATA2,"\n";
while(<DATA2>){
    print "in sim2.log: $_\n";
}

1.4文件信息

-A文件上一次被访问的时间(单位:天)
-B是否为二进制文件
-M文件上一次被修改的时间(单位:天)
-T是否为文本文件
-d为目录
-e文件或目录名存在
-f为普通文件
-l为符号链接
-p文件是命名管道(FIFO)
-s文件或目录存在且不为0(返回字节数)
-z文件存在,大小为0(目录恒为false),即是否为空文件,
my $file = "sim.log";
if(-e $file){
    say "is a file" if(-f _);   #_?
    #say "is a file" if(-f);    #等于-f $_,但$_不存在
    say "is a dir" if(-d _);
 }

 

2.目录

opendir DIRHANDLE, EXPR # 打开目录,打开脚本所在目录可能会出错

readdir DIRHANDLE # 读取目录

rewinddir DIRHANDLE # 定位指针到开头

telldir DIRHANDLE # 返回目录的当前位置

seekdir DIRHANDLE, POS # 定位指定到目录的 POS 位置

closedir DIRHANDLE # 关闭目录

#open DIR,"~/Proj/" or die "can't open dir: .,$!\n";    #不是open,是opendir
opendir DIR,"." or die "can't open dir: .,$!\n";

#way1
=head
标量环境每次循环返回一个文件名,直到遍历目录下所有元素,此时目录指针指向目录结尾,
如果需要再次读,需要rewinddir重定向目录指针到开头位置
=cut
while(readdir(DIR)){
    print $_."\n";
}
print "now position:",telldir(DIR),"\n";
rewinddir(DIR);
print "now position:",telldir(DIR),"\n";

my $firstFile = readdir(DIR);    #每次返回一个文件名,不是返回元素个数
print "\$firstFile=$firstFile\n";#first file

rewinddir(DIR);
my $fileNum = scalar readdir(DIR);    #依然返回第一个元素,不是元素个数!!!
print "\$fileNum=$fileNum\n";#first file too,not array size

rewinddir(DIR);
#way2
my @file = readdir(DIR);    #列表环境返回所有元素
foreach(@file){
    print $_."\n";#every file
}
close(DIR);
print "now close dir\n";

#way3
opendir DIR,"." or die "can't open dir: .,$!\n";
while($file = readdir(DIR)){    #读出元素的同时,进行赋值
    print $file."\n";
}

*mkdir-rmdir-chdir

if(not -e "test"){    #注意引号
    mkdir "test" or die "cannot mkdir";
}
opendir DIR,"." or die "cannot open die";
#while(grep /test/,readdir DIR){    #not work
foreach(grep /test/,readdir DIR){    #grep:grep /pattern/,ARRAY
    print $_,"\n";
}
chdir "test" or die "cannot chdir";
open(FILE,"+>","test.pl") or die "cannot open it";
system(ls); #output to screen
close DIR;
close FILE;
unlink "test.pl";
rmdir "../test";    #必须是空目录

*glob

相当于shell中的通配符,有2种形式:

1.@files = glob "*.pl";

2.@files = <*.pl>;perl检查<>中是否是句柄,不是则当成glob处理;

#my @file = glob "~/Proj/Perl/*.pl";    #与下句相同
my @file = <~/Proj/Perl/*.pl>;
#my $filestr = "~/Proj/Perl/*.pl";    #<>处理含通配符的变量时,变量需要加{}
#my @file = <${filestr}>;
foreach(@file){
    print $_."\n";
}

<>-glob-@ARGV-ARGV-$ARGV 

if(@ARGV){
    while(<>){  #同while(<ARGV>){,ARGV是@ARGV中的文件名的句柄
        say "$ARGV:\t$_";   #$ARGV是当前<>操作的句柄指向的文件名,$_是从文件读出的每一行.
    }
}
else{
    say "without para";    #若@ARGV为空,则<>从STDIN输入的文件中读取内容。
}


my @paraArray = @ARGV;
printf "\@paraArray:%s\n" x @paraArray,@paraArray;

#when para is not quotated by "". such as diamond.pl *.log
#my @paraExpand = <>;    #read all file directly 
#foreach(@paraExpand){
#    say;
#}

#when para is quotated by "". such as diamond.pl "*.log"
#my @paraExpand = <>;   #wrong.
my @paraExpand = <@ARGV>;   #here <> is glob operator 
foreach(@paraExpand){
    #while(<>){ #wrong,<>尝试读取@ARGV中的文件,同<ARGV>,ARGV是@ARGV中文件的句柄
    #while(<$_>){   #wrong,<>不能操作文件名.
        say ;   #every file name,not content
    #}
}
printf "%s\n" x @paraExpand,@paraExpand;

my $para = $ARGV[0];
say $para;
my @paraExpand = <${para}>; #glob operator
printf "%s\n" x @paraExpand,@paraExpand;
#my @paraError = <$para>;    #file_handle operator
#printf "%s\n" x @paraError,@paraError;

 

具体参考链接 

*shell中不在""内的通配符*,会自动展开,所以如果perl脚本命令行参数是这种形式,实际传进去的是展开后的参数列表。

*find 

下面为vim自动补全perl包名的脚本:

#! /usr/bin/perl
use strict;
use warnings;
use File::Find 'find';
#use Smart::Comments;

#补全模块所在文件
my $LIST_DIR = "$ENV{HOME}/.vim_extras/";
my $LIST_FILE = "file_perl_module";

unless(-e $LIST_DIR){
    mkdir $LIST_DIR or die "Couldn't create directory $LIST_DIR($!)\n";
}
open my $fh,">","$LIST_DIR$LIST_FILE" or die "Couldn't create file '$LIST_FILE'($!)\n";

my %already_seen;
my @incRev = (qw(/usr/share/perl/5.18.2),@INC);    #@INC目录不包含5.18.2目录
for my $incl_dir (@incRev){
    print "in dir:$incl_dir\n";
    find{
        wanted => sub{    #哈希形式:wanted=>匿名子程序引用
            my $file = $_;    #每次查找返回的文件名,是否包含路径视options而定
            return unless $file =~ /\.pm$/;
            ### 1
            ### $file    #smart comment自动打印变量,注释掉use后不打印
            $file =~ s#^\Q$incl_dir/\E##;#非单词加反斜杠,然后删掉不需要的目录前缀
            ### 2
            ### $file
            $file =~ s{/}{::}g;#::替换/
            ### 3
            ### $file
            $file =~ s#\.pm\z##;#去掉.pm后缀
            ### 4
            ### $file
            print {$fh} $file,"\n" unless $already_seen{$file}++;#去重
        },
        no_chdir => 1,#opt:不进入目录,返回的$_含目录信息,从当前目录开始
    },$incl_dir;    #也可以直接跟列表
}

#上面的find是下面这种形式,find 匿名哈希引用,搜索路径:
find({ wanted => /&process, follow => 1 }, '.');#follow?
如果不给option,可以进一步简写为这种形式,find 子程序引用,搜索路径:
find(\&func, @Dir);
sub func{
    #运用正则进行筛选
};

wanted指向的子程序中,有3个特殊变量:

$File::Find::dir 是当前目录全路径;
$_ 是当前文件名(不含路径);
$File::Find::name 是当前文件的完整路径。

具体参考链接

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值